unit UVFW;

interface

{$UNDEF UNICODE}
(* ***************************************************************************
  *
  *      VfW.H - Video for windows include file for WIN32
  *
  *      Copyright (c) 1991-1999, Microsoft Corp.  All rights reserved.
  *
  *      This include files defines interfaces to the following
  *      video components
  *
  *          COMPMAN         - Installable Compression Manager.
  *          DRAWDIB         - Routines for drawing to the display.
  *          VIDEO           - Video Capture Driver Interface
  *
  *          AVIFMT          - AVI File Format structure definitions.
  *          MMREG           - FOURCC and other things
  *
  *          AVIFile         - Interface for reading AVI Files and AVI Streams
  *          MCIWND          - MCI/AVI window class
  *          AVICAP          - AVI Capture Window class
  *
  *          MSACM           - Audio compression manager.
  *
  *      The following symbols control inclusion of various parts of this file:
  *
  *          NOCOMPMAN       - dont include COMPMAN
  *          NODRAWDIB       - dont include DRAWDIB
  *          NOVIDEO         - dont include video capture interface
  *
  *          NOAVIFMT        - dont include AVI file format structs
  *          NOMMREG         - dont include MMREG
  *
  *          NOAVIFILE       - dont include AVIFile interface
  *          NOMCIWND        - dont include AVIWnd class.
  *          NOAVICAP        - dont include AVICap class.
  *
  *          NOMSACM         - dont include ACM stuff.
  *
  *************************************************************************** *)

(* **************************************************************************** *)
(* *)
(* VFW.PAS Conversion by Ronald Dittrich *)
(* *)
(* E-Mail: info@swiftsoft.de *)
(* http://www.swiftsoft.de *)
(* *)
(* **************************************************************************** *)

(* **************************************************************************** *)
(* *)
(* Modyfied: 25.April.2000 *)
(* *)
(* E-Mail: *)
(* Ivo Steinmann: isteinmann@bluewin.ch *)
(* *)
(* Please send all messages regarding specific errors and lacks of this unit *)
(* to Ivo Steinmann *)
(* *)
(* **************************************************************************** *)

(* **************************************************************************** *)
(* *)
(* Modyfied: 2000-12-07 *)
(* *)
(* E-Mail: *)
(* Peter Haas: PeterJHaas@t-online.de *)
(* *)
(* Only modified line 1380  ( TAVIPALCHANGE.peNew ) *)
(* *)
(* **************************************************************************** *)

uses
  WinApi.Windows,
  WinApi.MMSystem,
  WinApi.Messages,
  WinApi.CommDlg,
  WinApi.ActiveX,
  Vcl.Dialogs;

(* ***************************************************************************
  *
  *  types
  *
  ************************************************************************** *)

type
  PVOID = pointer;
  LONG = longint;
  PLONG = ^LONG;
  int = integer;

  (* ***************************************************************************
    *
    *  VideoForWindowsVersion() - returns version of VfW
    *
    ************************************************************************** *)

function VideoForWindowsVersion: DWORD; pascal;

(* ***************************************************************************
  *
  *  call these to start stop using VfW from your app.
  *
  ************************************************************************** *)
{
  function InitVFW: LONG; stdcall;
  function TermVFW: LONG; stdcall; }

(* ***************************************************************************/
  /*                                                                          */
  /*        Macros                                                            */
  /*                                                                          */
  /*  should we define this??                                                 */
  /*                                                                          */
  /*************************************************************************** *)

function MKFOURCC(ch0, ch1, ch2, ch3: Char): FOURCC;

(* ***************************************************************************
  *
  *  COMPMAN - Installable Compression Manager.
  *
  *************************************************************************** *)

const
  ICVERSION = $0104;

type
  HIC = THandle; // Handle to an Installable Compressor

  //
  // this code in biCompression means the DIB must be accesed via
  // 48 bit pointers! using *ONLY* the selector given.
  //
const
  BI_1632 = $32333631; // '1632'

function mmioFOURCC(ch0, ch1, ch2, ch3: Char): FOURCC;

type
  TWOCC = word;

function aviTWOCC(ch0, ch1: Char): TWOCC;

const
  ICTYPE_VIDEO = $63646976; { vidc }
  ICTYPE_AUDIO = $63647561; { audc }

const
  ICERR_OK = 0;
  ICERR_DONTDRAW = 1;
  ICERR_NEWPALETTE = 2;
  ICERR_GOTOKEYFRAME = 3;
  ICERR_STOPDRAWING = 4;

  ICERR_UNSUPPORTED = -1;
  ICERR_BADFORMAT = -2;
  ICERR_MEMORY = -3;
  ICERR_INTERNAL = -4;
  ICERR_BADFLAGS = -5;
  ICERR_BADPARAM = -6;
  ICERR_BADSIZE = -7;
  ICERR_BADHANDLE = -8;
  ICERR_CANTUPDATE = -9;
  ICERR_ABORT = -10;
  ICERR_ERROR = -100;
  ICERR_BADBITDEPTH = -200;
  ICERR_BADIMAGESIZE = -201;

  ICERR_CUSTOM = -400; // errors less than ICERR_CUSTOM...

  { -- Values for dwFlags of ICOpen() ------------------------------------------- }

  ICMODE_COMPRESS = 1;
  ICMODE_DECOMPRESS = 2;
  ICMODE_FASTDECOMPRESS = 3;
  ICMODE_QUERY = 4;
  ICMODE_FASTCOMPRESS = 5;
  ICMODE_DRAW = 8;

  { -- Flags for AVI file index ------------------------------------------------- }

  AVIIF_LIST = $00000001;
  AVIIF_TWOCC = $00000002;
  AVIIF_KEYFRAME = $00000010;

  { -- quality flags ------------------------------------------------------------ }

  ICQUALITY_LOW = 0;
  ICQUALITY_HIGH = 10000;
  ICQUALITY_DEFAULT = -1;

  (* ***********************************************************************
    *********************************************************************** *)

  ICM_USER = (DRV_USER + $0000);

  ICM_RESERVED_LOW = (DRV_USER + $1000);
  ICM_RESERVED_HIGH = (DRV_USER + $2000);
  ICM_RESERVED = ICM_RESERVED_LOW;

  (* ***********************************************************************

    messages.

    *********************************************************************** *)

  ICM_GETSTATE = (ICM_RESERVED + 0); // Get compressor state
  ICM_SETSTATE = (ICM_RESERVED + 1); // Set compressor state
  ICM_GETINFO = (ICM_RESERVED + 2); // Query info about the compressor

  ICM_CONFIGURE = (ICM_RESERVED + 10); // show the configure dialog
  ICM_ABOUT = (ICM_RESERVED + 11); // show the about box

  ICM_GETDEFAULTQUALITY = (ICM_RESERVED + 30);
  // get the default value for quality
  ICM_GETQUALITY = (ICM_RESERVED + 31); // get the current value for quality
  ICM_SETQUALITY = (ICM_RESERVED + 32); // set the default value for quality

  ICM_SET = (ICM_RESERVED + 40); // Tell the driver something
  ICM_GET = (ICM_RESERVED + 41); // Ask the driver something

  { -- Constants for ICM_SET: --------------------------------------------------- }

  ICM_FRAMERATE = $526D7246; { FrmR }
  ICM_KEYFRAMERATE = $5279654B; { KeyR }

  (* ***********************************************************************

    ICM specific messages.

    *********************************************************************** *)

  ICM_COMPRESS_GET_FORMAT = (ICM_USER + 4); // get compress format or size
  ICM_COMPRESS_GET_SIZE = (ICM_USER + 5); // get output size
  ICM_COMPRESS_QUERY = (ICM_USER + 6); // query support for compress
  ICM_COMPRESS_BEGIN = (ICM_USER + 7); // begin a series of compress calls.
  ICM_COMPRESS = (ICM_USER + 8); // compress a frame
  ICM_COMPRESS_END = (ICM_USER + 9); // end of a series of compress calls.

  ICM_DECOMPRESS_GET_FORMAT = (ICM_USER + 10); // get decompress format or size
  ICM_DECOMPRESS_QUERY = (ICM_USER + 11); // query support for dempress
  ICM_DECOMPRESS_BEGIN = (ICM_USER + 12); // start a series of decompress calls
  ICM_DECOMPRESS = (ICM_USER + 13); // decompress a frame
  ICM_DECOMPRESS_END = (ICM_USER + 14); // end a series of decompress calls
  ICM_DECOMPRESS_SET_PALETTE = (ICM_USER + 29); // fill in the DIB color table
  ICM_DECOMPRESS_GET_PALETTE = (ICM_USER + 30); // fill in the DIB color table

  ICM_DRAW_QUERY = (ICM_USER + 31); // query support for dempress
  ICM_DRAW_BEGIN = (ICM_USER + 15); // start a series of draw calls
  ICM_DRAW_GET_PALETTE = (ICM_USER + 16); // get the palette needed for drawing
  ICM_DRAW_START = (ICM_USER + 18); // start decompress clock
  ICM_DRAW_STOP = (ICM_USER + 19); // stop decompress clock
  ICM_DRAW_END = (ICM_USER + 21); // end a series of draw calls
  ICM_DRAW_GETTIME = (ICM_USER + 32); // get value of decompress clock
  ICM_DRAW = (ICM_USER + 33); // generalized "render" message
  ICM_DRAW_WINDOW = (ICM_USER + 34); // drawing window has moved or hidden
  ICM_DRAW_SETTIME = (ICM_USER + 35); // set correct value for decompress clock
  ICM_DRAW_REALIZE = (ICM_USER + 36); // realize palette for drawing
  ICM_DRAW_FLUSH = (ICM_USER + 37); // clear out buffered frames
  ICM_DRAW_RENDERBUFFER = (ICM_USER + 38); // draw undrawn things in queue

  ICM_DRAW_START_PLAY = (ICM_USER + 39); // start of a play
  ICM_DRAW_STOP_PLAY = (ICM_USER + 40); // end of a play

  ICM_DRAW_SUGGESTFORMAT = (ICM_USER + 50); // Like ICGetDisplayFormat
  ICM_DRAW_CHANGEPALETTE = (ICM_USER + 51); // for animating palette

  ICM_GETBUFFERSWANTED = (ICM_USER + 41); // ask about prebuffering

  ICM_GETDEFAULTKEYFRAMERATE = (ICM_USER + 42);
  // get the default value for key frames

  ICM_DECOMPRESSEX_BEGIN = (ICM_USER + 60);
  // start a series of decompress calls
  ICM_DECOMPRESSEX_QUERY = (ICM_USER + 61);
  // start a series of decompress calls
  ICM_DECOMPRESSEX = (ICM_USER + 62); // decompress a frame
  ICM_DECOMPRESSEX_END = (ICM_USER + 63); // end a series of decompress calls

  ICM_COMPRESS_FRAMES_INFO = (ICM_USER + 70); // tell about compress to come
  ICM_SET_STATUS_PROC = (ICM_USER + 72); // set status callback

  (* ***********************************************************************
    *********************************************************************** *)

type
  PICOPEN = ^TICOPEN;

  TICOPEN = packed record
    dwSize: DWORD; // sizeof(ICOPEN)
    fccType: DWORD; // 'vidc'
    fccHandler: DWORD; //
    dwVersion: DWORD; // version of compman opening you
    dwFlags: DWORD; // LOWORD is type specific
    dwError: DWORD; // error return.
    pV1Reserved: PVOID; // Reserved
    pV2Reserved: PVOID; // Reserved
    dnDevNode: DWORD; // Devnode for PnP devices
  end;

  (* ***********************************************************************
    *********************************************************************** *)

  PICINFO = ^TICINFO;

  TICINFO = packed record
    dwSize: DWORD; // sizeof(ICINFO)
    fccType: DWORD; // compressor type     'vidc' 'audc'
    fccHandler: DWORD; // compressor sub-type 'rle ' 'jpeg' 'pcm '
    dwFlags: DWORD; // flags LOWORD is type specific
    dwVersion: DWORD; // version of the driver
    dwVersionICM: DWORD; // version of the ICM used
    //
    // under Win32, the driver always returns UNICODE strings.
    //
    szName: array [0 .. 15] of WChar; // short name
    szDescription: array [0 .. 127] of WChar; // DWORD name
    szDriver: array [0 .. 127] of WChar; // driver that contains compressor
  end;

  { -- Flags for the <dwFlags> field of the <ICINFO> structure. ------------ }

const
  VIDCF_QUALITY = $0001; // supports quality
  VIDCF_CRUNCH = $0002; // supports crunching to a frame size
  VIDCF_TEMPORAL = $0004; // supports inter-frame compress
  VIDCF_COMPRESSFRAMES = $0008; // wants the compress all frames message
  VIDCF_DRAW = $0010; // supports drawing
  VIDCF_FASTTEMPORALC = $0020; // does not need prev frame on compress
  VIDCF_FASTTEMPORALD = $0080; // does not need prev frame on decompress
  // VIDCF_QUALITYTIME         = $0040 ;  // supports temporal quality

  // VIDCF_FASTTEMPORAL        = (VIDCF_FASTTEMPORALC or VIDCF_FASTTEMPORALD)

  (* ***********************************************************************
    *********************************************************************** *)

  ICCOMPRESS_KEYFRAME = $00000001;

type
  PICCOMPRESS = ^TICCOMPRESS;

  TICCOMPRESS = packed record
    dwFlags: DWORD; // flags

    lpbiOutput: PBITMAPINFOHEADER; // output format
    lpOutput: PVOID; // output data

    lpbiInput: PBITMAPINFOHEADER; // format of frame to compress
    lpInput: PVOID; // frame data to compress

    lpckid: PDWORD; // ckid for data in AVI file
    lpdwFlags: PDWORD; // flags in the AVI index.
    lFrameNum: LONG; // frame number of seq.
    dwFrameSize: DWORD; // reqested size in bytes. (if non zero)

    dwQuality: DWORD; // quality

    // these are new fields

    lpbiPrev: PBITMAPINFOHEADER; // format of previous frame
    lpPrev: PVOID; // previous frame
  end;

  (* ***********************************************************************
    *********************************************************************** *)

const
  ICCOMPRESSFRAMES_PADDING = $00000001;

type
  TICCompressProc = function(lInputOutput: LPARAM; lFrame: DWORD; lpBits: PVOID;
    len: LONG): LONG; stdcall;

  PICCOMPRESSFRAMES = ^TICCOMPRESSFRAMES;

  TICCOMPRESSFRAMES = packed record
    dwFlags: DWORD; // flags

    lpbiOutput: PBITMAPINFOHEADER; // output format
    lOutput: LPARAM; // output identifier

    lpbiInput: PBITMAPINFOHEADER; // format of frame to compress
    lInput: LPARAM; // input identifier

    lStartFrame: LONG; // start frame
    lFrameCount: LONG; // # of frames

    lQuality: LONG; // quality
    lDataRate: LONG; // data rate
    lKeyRate: LONG; // key frame rate

    dwRate: DWORD; // frame rate, as always
    dwScale: DWORD;

    dwOverheadPerFrame: DWORD;
    dwReserved2: DWORD;

    GetData: TICCompressProc;
    PutData: TICCompressProc;
  end;

  { -- Messages for Status callback --------------------------------------------- }

const
  ICSTATUS_START = 0;
  ICSTATUS_STATUS = 1; // l = % done
  ICSTATUS_END = 2;
  ICSTATUS_ERROR = 3; // l = error string (LPSTR)
  ICSTATUS_YIELD = 4;

type
  // return nonzero means abort operation in progress
  TICStatusProc = function(LPARAM: LPARAM; message: UINT; l: LONG)
    : LONG; stdcall;

  PICSETSTATUSPROC = ^TICSETSTATUSPROC;

  TICSETSTATUSPROC = packed record
    dwFlags: DWORD;
    LPARAM: LPARAM;
    Status: TICStatusProc;
  end;

  (* ***********************************************************************
    *********************************************************************** *)

const
  ICDECOMPRESS_HURRYUP = $80000000; // don't draw just buffer (hurry up!)
  ICDECOMPRESS_UPDATE = $40000000; // don't draw just update screen
  ICDECOMPRESS_PREROLL = $20000000; // this frame is before real start
  ICDECOMPRESS_NULLFRAME = $10000000; // repeat last frame
  ICDECOMPRESS_NOTKEYFRAME = $08000000; // this frame is not a key frame

type
  PICDECOMPRESS = ^TICDECOMPRESS;

  TICDECOMPRESS = packed record
    dwFlags: DWORD; // flags (from AVI index...)
    lpbiInput: PBITMAPINFOHEADER; // BITMAPINFO of compressed data
    // biSizeImage has the chunk size
    lpInput: PVOID; // compressed data
    lpbiOutput: PBITMAPINFOHEADER; // DIB to decompress to
    lpOutput: PVOID;
    ckid: DWORD; // ckid from AVI file
  end;

  PICDECOMPRESSEX = ^TICDECOMPRESSEX;

  TICDECOMPRESSEX = packed record

    //
    // same as ICM_DECOMPRESS
    //

    dwFlags: DWORD;
    lpbiSrc: PBITMAPINFOHEADER; // BITMAPINFO of compressed data
    lpSrc: PVOID; // compressed data
    lpbiDst: PBITMAPINFOHEADER; // DIB to decompress to
    lpDst: PVOID; // output data

    //
    // new for ICM_DECOMPRESSEX
    //

    xDst: int; // destination rectangle
    yDst: int;
    dxDst: int;
    dyDst: int;

    xSrc: int; // source rectangle
    ySrc: int;
    dxSrc: int;
    dySrc: int;
  end;

  (* ***********************************************************************
    *********************************************************************** *)

const
  ICDRAW_QUERY = $00000001; // test for support
  ICDRAW_FULLSCREEN = $00000002; // draw to full screen
  ICDRAW_HDC = $00000004; // draw to a HDC/HWND
  ICDRAW_ANIMATE = $00000008; // expect palette animation
  ICDRAW_CONTINUE = $00000010; // draw is a continuation of previous draw
  ICDRAW_MEMORYDC = $00000020; // DC is offscreen, by the way
  ICDRAW_UPDATING = $00000040; // We're updating, as opposed to playing
  ICDRAW_RENDER = $00000080; // used to render data not draw it
  ICDRAW_BUFFER = $00000100;
  // please buffer this data offscreen, we will need to update it

type
  PICDRAWBEGIN = ^TICDRAWBEGIN;

  TICDRAWBEGIN = packed record
    dwFlags: DWORD; // flags

    hpal: HPALETTE; // palette to draw with
    hwnd: hwnd; // window to draw to
    hdc: hdc; // HDC to draw to

    xDst: int; // destination rectangle
    yDst: int;
    dxDst: int;
    dyDst: int;

    lpbi: PBITMAPINFOHEADER;
    // format of frame to draw

    xSrc: int; // source rectangle
    ySrc: int;
    dxSrc: int;
    dySrc: int;

    dwRate: DWORD; // frames/second = (dwRate/dwScale)
    dwScale: DWORD;
  end;

  (* ***********************************************************************
    *********************************************************************** *)

const
  ICDRAW_HURRYUP = $80000000; // don't draw just buffer (hurry up!)
  ICDRAW_UPDATE = $40000000; // don't draw just update screen
  ICDRAW_PREROLL = $20000000; // this frame is before real start
  ICDRAW_NULLFRAME = $10000000; // repeat last frame
  ICDRAW_NOTKEYFRAME = $08000000; // this frame is not a key frame

type
  PICDRAW = ^TICDRAW;

  TICDRAW = packed record
    dwFlags: DWORD; // flags
    lpFormat: PVOID; // format of frame to decompress
    lpData: PVOID; // frame data to decompress
    cbData: DWORD;
    lTime: LONG; // time in drawbegin units (see dwRate and dwScale)
  end;

  PICDRAWSUGGEST = ^TICDRAWSUGGEST;

  TICDRAWSUGGEST = packed record
    lpbiIn: PBITMAPINFOHEADER; // format to be drawn
    lpbiSuggest: PBITMAPINFOHEADER;
    // location for suggested format (or NULL to get size)
    dxSrc: int; // source extent or 0
    dySrc: int;
    dxDst: int; // dest extent or 0
    dyDst: int;
    hicDecompressor: HIC; // decompressor you can talk to
  end;

  (* ***********************************************************************
    *********************************************************************** *)

  PICPALETTE = ^TICPALETTE;

  TICPALETTE = packed record
    dwFlags: DWORD; // flags (from AVI index...)
    iStart: int; // first palette to change
    iLen: int; // count of entries to change.
    lppe: PPALETTEENTRY; // palette
  end;

  (* ***********************************************************************

    ICM function declarations

    *********************************************************************** *)

function ICInfo(fccType, fccHandler: DWORD; lpicinfo: PICINFO): BOOL; stdcall;
function ICInstall(fccType, fccHandler: DWORD; LPARAM: LPARAM; szDesc: LPSTR;
  wFlags: UINT): BOOL; stdcall;
function ICRemove(fccType, fccHandler: DWORD; wFlags: UINT): BOOL; stdcall;
function ICGetInfo(HIC: HIC; PICINFO: PICINFO; cb: DWORD): DWORD; stdcall;

function ICOpen(fccType, fccHandler: DWORD; wMode: UINT): HIC; stdcall;
function ICOpenFunction(fccType, fccHandler: DWORD; wMode: UINT;
  lpfnHandler: TFarProc): HIC; stdcall;
function ICClose(HIC: HIC): DWORD; stdcall;

function ICSendMessage(HIC: HIC; msg: UINT; dw1, dw2: DWORD): DWORD; stdcall;

{ -- Values for wFlags of ICInstall ------------------------------------------- }

const
  ICINSTALL_UNICODE = $8000;

  ICINSTALL_FUNCTION = $0001; // lParam is a DriverProc (function ptr)
  ICINSTALL_DRIVER = $0002; // lParam is a driver name (string)
  ICINSTALL_HDRV = $0004; // lParam is a HDRVR (driver handle)

  ICINSTALL_DRIVERW = $8002; // lParam is a unicode driver name

  { -- Query macros ------------------------------------------------------------- }

  ICMF_CONFIGURE_QUERY = $00000001;
  ICMF_ABOUT_QUERY = $00000001;

function ICQueryAbout(HIC: HIC): BOOL;
function ICAbout(HIC: HIC; hwnd: hwnd): DWORD;
function ICQueryConfigure(HIC: HIC): BOOL;
function ICConfigure(HIC: HIC; hwnd: hwnd): DWORD;

{ -- Get/Set state macros ----------------------------------------------------- }

function ICGetState(HIC: HIC; pv: PVOID; cb: DWORD): DWORD;
function ICSetState(HIC: HIC; pv: PVOID; cb: DWORD): DWORD;
function ICGetStateSize(HIC: HIC): DWORD;

{ -- Get value macros --------------------------------------------------------- }

function ICGetDefaultQuality(HIC: HIC): DWORD;
function ICGetDefaultKeyFrameRate(HIC: HIC): DWORD;

{ -- Draw window macro -------------------------------------------------------- }

function ICDrawWindow(HIC: HIC; prc: PRECT): DWORD;

(* ***********************************************************************

  compression functions

  ************************************************************************/
  /*
  *  ICCompress()
  *
  *  compress a single frame
  *
*)
function ICCompress(HIC: HIC; dwFlags: DWORD; // flags
  lpbiOutput: PBITMAPINFOHEADER; // output format
  lpData: PVOID; // output data
  lpbiInput: PBITMAPINFOHEADER; // format of frame to compress
  lpBits: PVOID; // frame data to compress
  lpckid: PDWORD; // ckid for data in AVI file
  lpdwFlags: PDWORD; // flags in the AVI index.
  lFrameNum: DWORD; // frame number of seq.
  dwFrameSize: DWORD; // reqested size in bytes. (if non zero)
  dwQuality: DWORD; // quality within one frame
  lpbiPrev: PBITMAPINFOHEADER; // format of previous frame
  lpPrev: PVOID // previous frame
  ): DWORD; cdecl;

(*
  *  ICCompressBegin()
  *
  *  start compression from a source format (lpbiInput) to a dest
  *  format (lpbiOuput) is supported.
  *
*)

function ICCompressBegin(HIC: HIC; lpbiInput: PBITMAPINFOHEADER;
  lpbiOutput: PBITMAPINFOHEADER): DWORD;

(*
  *  ICCompressQuery()
  *
  *  determines if compression from a source format (lpbiInput) to a dest
  *  format (lpbiOuput) is supported.
  *
*)

function ICCompressQuery(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;

(*
  *  ICCompressGetFormat()
  *
  *  get the output format, (format of compressed data)
  *  if lpbiOutput is NULL return the size in bytes needed for format.
  *
*)

function ICCompressGetFormat(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
function ICCompressGetFormatSize(HIC: HIC; lpbi: PBITMAPINFOHEADER): DWORD;

(*
  *  ICCompressSize()
  *
  *  return the maximal size of a compressed frame
  *
*)

function ICCompressGetSize(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
function ICCompressEnd(HIC: HIC): DWORD;

(* ***********************************************************************

  decompression functions

  *********************************************************************** *)

(*
  *  ICDecompress()
  *
  *  decompress a single frame
  *
*)

function ICDecompress(HIC: HIC; dwFlags: DWORD; // flags (from AVI index...)
  lpbiFormat: PBITMAPINFOHEADER; // BITMAPINFO of compressed data
  // biSizeImage has the chunk size
  lpData: PVOID; // data
  lpbi: PBITMAPINFOHEADER; // DIB to decompress to
  lpBits: PVOID): DWORD; cdecl;

(*
  *  ICDecompressBegin()
  *
  *  start compression from a source format (lpbiInput) to a dest
  *  format (lpbiOutput) is supported.
  *
*)

function ICDecompressBegin(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;

(*
  *  ICDecompressQuery()
  *
  *  determines if compression from a source format (lpbiInput) to a dest
  *  format (lpbiOutput) is supported.
  *
*)

function ICDecompressQuery(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;

(*
  *  ICDecompressGetFormat()
  *
  *  get the output format, (format of un-compressed data)
  *  if lpbiOutput is NULL return the size in bytes needed for format.
  *
*)

function ICDecompressGetFormat(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
function ICDecompressGetFormatSize(HIC: HIC; lpbi: PBITMAPINFOHEADER): DWORD;

(*
  *  ICDecompressGetPalette()
  *
  *  get the output palette
  *
*)

function ICDecompressGetPalette(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
function ICDecompressSetPalette(HIC: HIC;
  lpbiPalette: PBITMAPINFOHEADER): DWORD;

function ICDecompressEnd(HIC: HIC): DWORD;

(* ***********************************************************************

  decompression (ex) functions

  *********************************************************************** *)

//
// on Win16 these functions are macros that call ICMessage. ICMessage will
// not work on NT. rather than add new entrypoints we have given
// them as static inline functions
//

(*
  *  ICDecompressEx()
  *
  *  decompress a single frame
  *
*)

function ICDecompressEx(HIC: HIC; dwFlags: DWORD; lpbiSrc: PBITMAPINFOHEADER;
  lpSrc: PVOID; xSrc: int; ySrc: int; dxSrc: int; dySrc: int;
  lpbiDst: PBITMAPINFOHEADER; lpDst: PVOID; xDst: int; yDst: int; dxDst: int;
  dyDst: int): DWORD; stdcall;

(*
  *  ICDecompressExBegin()
  *
  *  start compression from a source format (lpbiInput) to a dest
  *  format (lpbiOutput) is supported.
  *
*)

function ICDecompressExBegin(HIC: HIC; dwFlags: DWORD;
  lpbiSrc: PBITMAPINFOHEADER; lpSrc: PVOID; xSrc: int; ySrc: int; dxSrc: int;
  dySrc: int; lpbiDst: PBITMAPINFOHEADER; lpDst: PVOID; xDst: int; yDst: int;
  dxDst: int; dyDst: int): DWORD; stdcall;

(*
  *  ICDecompressExQuery()
  *
*)

function ICDecompressExQuery(HIC: HIC; dwFlags: DWORD;
  lpbiSrc: PBITMAPINFOHEADER; lpSrc: PVOID; xSrc: int; ySrc: int; dxSrc: int;
  dySrc: int; lpbiDst: PBITMAPINFOHEADER; lpDst: PVOID; xDst: int; yDst: int;
  dxDst: int; dyDst: int): DWORD; stdcall;

function ICDecompressExEnd(HIC: HIC): DWORD;

(* ***********************************************************************

  drawing functions

  *********************************************************************** *)

(*
  *  ICDrawBegin()
  *
  *  start decompressing data with format (lpbiInput) directly to the screen
  *
  *  return zero if the decompressor supports drawing.
  *
*)

function ICDrawBegin(HIC: HIC; dwFlags: DWORD; // flags
  hpal: HPALETTE; // palette to draw with
  hwnd: hwnd; // window to draw to
  hdc: hdc; // HDC to draw to
  xDst: int; // destination rectangle
  yDst: int; dxDst: int; dyDst: int; lpbi: PBITMAPINFOHEADER;
  // format of frame to draw
  xSrc: int; // source rectangle
  ySrc: int; dxSrc: int; dySrc: int; dwRate: DWORD;
  // frames/second = (dwRate/dwScale)
  dwScale: DWORD): DWORD; cdecl;

(*
  *  ICDraw()
  *
  *  decompress data directly to the screen
  *
*)

function ICDraw(HIC: HIC; dwFlags: DWORD; // flags
  lpFormat: PVOID; // format of frame to decompress
  lpData: PVOID; // frame data to decompress
  cbData: DWORD; // size of data
  lTime: DWORD // time to draw this frame
  ): DWORD; cdecl;

// ICMessage is not supported on Win32, so provide a static inline function
// to do the same job
function ICDrawSuggestFormat(HIC: HIC; lpbiIn: PBITMAPINFOHEADER;
  lpbiOut: PBITMAPINFOHEADER; dxSrc: int; dySrc: int; dxDst: int; dyDst: int;
  hicDecomp: HIC): DWORD; stdcall;

(*
  *  ICDrawQuery()
  *
  *  determines if the compressor is willing to render the specified format.
  *
*)

function ICDrawQuery(HIC: HIC; lpbiInput: PBITMAPINFOHEADER): DWORD;
function ICDrawChangePalette(HIC: HIC; lpbiInput: PBITMAPINFOHEADER): DWORD;
function ICGetBuffersWanted(HIC: HIC; lpdwBuffers: PDWORD): DWORD;
function ICDrawEnd(HIC: HIC): DWORD;
function ICDrawStart(HIC: HIC): DWORD;
function ICDrawStartPlay(HIC: HIC; lFrom, lTo: DWORD): DWORD;
function ICDrawStop(HIC: HIC): DWORD;
function ICDrawStopPlay(HIC: HIC): DWORD;
function ICDrawGetTime(HIC: HIC; lplTime: PDWORD): DWORD;
function ICDrawSetTime(HIC: HIC; lTime: DWORD): DWORD;
function ICDrawRealize(HIC: HIC; hdc: hdc; fBackground: BOOL): DWORD;
function ICDrawFlush(HIC: HIC): DWORD;
function ICDrawRenderBuffer(HIC: HIC): DWORD;

(* ***********************************************************************

  Status callback functions

  ************************************************************************/

  /*
  *  ICSetStatusProc()
  *
  *  Set the status callback function
  *
*)

// ICMessage is not supported on NT
function ICSetStatusProc(HIC: HIC; dwFlags: DWORD; LPARAM: DWORD;
  fpfnStatus: TICStatusProc): DWORD; stdcall;

(* ***********************************************************************

  helper routines for DrawDib and MCIAVI...

  *********************************************************************** *)

function ICLocate(fccType, fccHandler: DWORD;
  lpbiIn, lpbiOut: PBITMAPINFOHEADER; wFlags: word): HIC; stdcall;
function ICGetDisplayFormat(HIC: HIC; lpbiIn, lpbiOut: PBITMAPINFOHEADER;
  BitDepth: int; dx, dy: int): HIC; stdcall;

function ICDecompressOpen(fccType, fccHandler: DWORD;
  lpbiIn, lpbiOut: PBITMAPINFOHEADER): HIC;
function ICDrawOpen(fccType, fccHandler: DWORD; lpbiIn: PBITMAPINFOHEADER): HIC;

(* ***********************************************************************
  Higher level functions
  *********************************************************************** *)

function ICImageCompress(HIC: HIC; // compressor to use
  uiFlags: UINT; // flags (none yet)
  lpbiIn: PBITMAPINFO; // format to compress from
  lpBits: PVOID; // data to compress
  lpbiOut: PBITMAPINFO; // compress to this (NULL ==> default)
  lQuality: LONG; // quality to use
  plSize: PDWORD // compress to this size (0=whatever)
  ): THandle; stdcall;

function ICImageDecompress(HIC: HIC; // compressor to use
  uiFlags: UINT; // flags (none yet)
  lpbiIn: PBITMAPINFO; // format to decompress from
  lpBits: PVOID; // data to decompress
  lpbiOut: PBITMAPINFO // decompress to this (NULL ==> default)
  ): THandle; stdcall;

{ -- TCompVars ---------------------------------------------------------------- }

//
// Structure used by ICSeqCompressFrame and ICCompressorChoose routines
// Make sure this matches the autodoc in icm.c!
//

type
  PCOMPVARS = ^TCOMPVARS;

  TCOMPVARS = packed record
    cbSize: DWORD; // set to sizeof(COMPVARS) before
    // calling ICCompressorChoose
    dwFlags: DWORD; // see below...
    HIC: HIC; // HIC of chosen compressor
    fccType: DWORD; // basically ICTYPE_VIDEO
    fccHandler: DWORD; // handler of chosen compressor or
    // "" or "DIB "
    lpbiIn: PBITMAPINFO; // input format
    lpbiOut: PBITMAPINFO; // output format - will compress to this
    lpBitsOut: PVOID;
    lpBitsPrev: PVOID;
    lFrame: LONG;
    lKey: LONG; // key frames how often?
    lDataRate: LONG; // desired data rate KB/Sec
    lQ: LONG; // desired quality
    lKeyCount: LONG;
    lpState: PVOID; // state of compressor
    cbState: LONG; // size of the state
  end;

  // FLAGS for dwFlags element of COMPVARS structure:
  // set this flag if you initialize COMPVARS before calling ICCompressorChoose

const
  ICMF_COMPVARS_VALID = $00000001; // COMPVARS contains valid data

  //
  // allows user to choose compressor, quality etc...
  //
function ICCompressorChoose(hwnd: hwnd; // parent window for dialog
  uiFlags: UINT; // flags
  pvIn: PVOID; // input format (optional)
  lpData: PVOID; // input data (optional)
  pc: PCOMPVARS; // data about the compressor/dlg
  lpszTitle: LPSTR // dialog title (optional)
  ): BOOL; stdcall;

// defines for uiFlags

const
  ICMF_CHOOSE_KEYFRAME = $0001; // show KeyFrame Every box
  ICMF_CHOOSE_DATARATE = $0002; // show DataRate box
  ICMF_CHOOSE_PREVIEW = $0004; // allow expanded preview dialog
  ICMF_CHOOSE_ALLCOMPRESSORS = $0008; // don't only show those that
  // can handle the input format
  // or input data

function ICSeqCompressFrameStart(pc: PCOMPVARS; lpbiIn: PBITMAPINFO)
  : BOOL; stdcall;
procedure ICSeqCompressFrameEnd(pc: PCOMPVARS); stdcall;

function ICSeqCompressFrame(pc: PCOMPVARS; // set by ICCompressorChoose
  uiFlags: UINT; // flags
  lpBits: PVOID; // input DIB bits
  pfKey: PBOOL; // did it end up being a key frame?
  plSize: PDWORD // size to compress to/of returned image
  ): PVOID; stdcall;

procedure ICCompressorFree(pc: PCOMPVARS); stdcall;

(* *************************************************************************
  *
  *  DRAWDIB - Routines for drawing to the display.
  *
  ************************************************************************ *)

type
  HDRAWDIB = THandle; // hdd

  (* ********************************************************************

    DrawDib Flags

    ********************************************************************* *)

const
  DDF_UPDATE = $0002; // re-draw the last DIB
  DDF_SAME_HDC = $0004; // HDC same as last call (all setup)
  DDF_SAME_DRAW = $0008; // draw params are the same
  DDF_DONTDRAW = $0010; // dont draw frame, just decompress
  DDF_ANIMATE = $0020; // allow palette animation
  DDF_BUFFER = $0040; // always buffer image
  DDF_JUSTDRAWIT = $0080; // just draw it with GDI
  DDF_FULLSCREEN = $0100; // use DisplayDib
  DDF_BACKGROUNDPAL = $0200; // Realize palette in background
  DDF_NOTKEYFRAME = $0400; // this is a partial frame update, hint
  DDF_HURRYUP = $0800; // hurry up please!
  DDF_HALFTONE = $1000; // always halftone

  DDF_PREROLL = DDF_DONTDRAW; // Builing up a non-keyframe
  DDF_SAME_DIB = DDF_SAME_DRAW;
  DDF_SAME_SIZE = DDF_SAME_DRAW;

  (* ********************************************************************

    DrawDib functions

    ******************************************************************** *)

  { -- DrawDibOpen() ------------------------------------------------------------ }

function DrawDibOpen: HDRAWDIB; stdcall;

{ -- DrawDibClose() ----------------------------------------------------------- }

function DrawDibClose(hdd: HDRAWDIB): BOOL; stdcall;

{ -- DrawDibGetBuffer() ------------------------------------------------------- }

function DrawDibGetBuffer(hdd: HDRAWDIB; lpbi: PBITMAPINFOHEADER; dwSize: DWORD;
  dwFlags: DWORD): PVOID; stdcall;

{ -- DrawDibGetPalette() - get the palette used for drawing DIBs -------------- }

function DrawDibGetPalette(hdd: HDRAWDIB): HPALETTE; stdcall;

{ -- DrawDibSetPalette() - set the palette used for drawing DIBs -------------- }

function DrawDibSetPalette(hdd: HDRAWDIB; hpal: HPALETTE): BOOL; stdcall;

{ -- DrawDibChangePalette() --------------------------------------------------- }

function DrawDibChangePalette(hdd: HDRAWDIB; iStart, iLen: int;
  lppe: PPALETTEENTRY): BOOL; stdcall;

{ -- DrawDibRealize() - realize the palette in a HDD -------------------------- }

function DrawDibRealize(hdd: HDRAWDIB; hdc: hdc; fBackground: BOOL)
  : UINT; stdcall;

{ -- DrawDibStart() - start of streaming playback ----------------------------- }

function DrawDibStart(hdd: HDRAWDIB; rate: DWORD): BOOL; stdcall;

{ -- DrawDibStop() - start of streaming playback ------------------------------ }

function DrawDibStop(hdd: HDRAWDIB): BOOL; stdcall;

{ -- DrawDibBegin() - prepare to draw ----------------------------------------- }

function DrawDibBegin(hdd: HDRAWDIB; hdc: hdc; dxDst: int; dyDst: int;
  lpbi: PBITMAPINFOHEADER; dxSrc: int; dySrc: int; wFlags: UINT): BOOL; stdcall;

{ -- DrawDibDraw() - actually draw a DIB to the screen ------------------------ }

function DrawDibDraw(hdd: HDRAWDIB; hdc: hdc; xDst: int; yDst: int; dxDst: int;
  dyDst: int; lpbi: PBITMAPINFOHEADER; lpBits: PVOID; xSrc: int; ySrc: int;
  dxSrc: int; dySrc: int; wFlags: UINT): BOOL; stdcall;

{ -- DrawDibUpdate() - redraw last image (may only be valid with DDF_BUFFER) -- }

function DrawDibUpdate(hdd: HDRAWDIB; hdc: hdc; x, y: int): BOOL;

{ -- DrawDibEnd() ------------------------------------------------------------- }

function DrawDibEnd(hdd: HDRAWDIB): BOOL; stdcall;

{ -- DrawDibTime() - for debugging purposes only ------------------------------ }

type
  PDRAWDIBTIME = ^TDRAWDIBTIME;

  TDRAWDIBTIME = packed record
    timeCount: LONG;
    timeDraw: LONG;
    timeDecompress: LONG;
    timeDither: LONG;
    timeStretch: LONG;
    timeBlt: LONG;
    timeSetDIBits: LONG;
  end;

function DrawDibTime(hdd: HDRAWDIB; lpddtime: PDRAWDIBTIME): BOOL; stdcall;

{ -- Display profiling -------------------------------------------------------- }

const
  PD_CAN_DRAW_DIB = $0001; // if you can draw at all
  PD_CAN_STRETCHDIB = $0002; // basicly RC_STRETCHDIB
  PD_STRETCHDIB_1_1_OK = $0004; // is it fast?
  PD_STRETCHDIB_1_2_OK = $0008; // ...
  PD_STRETCHDIB_1_N_OK = $0010; // ...

function DrawDibProfileDisplay(lpbi: PBITMAPINFOHEADER): DWORD; stdcall;

(* ***************************************************************************
  *
  *  AVIFMT - AVI file format definitions
  *
  *************************************************************************** *)

//
// The following is a short description of the AVI file format.  Please
// see the accompanying documentation for a full explanation.
//
// An AVI file is the following RIFF form:
//
// RIFF('AVI'
// LIST('hdrl'
// avih(<MainAVIHeader>)
// LIST ('strl'
// strh(<Stream header>)
// strf(<Stream format>)
// ... additional header data
// LIST('movi'
// { LIST('rec'
// SubChunk...
// )
// | SubChunk } ....
// )
// [ <AVIIndex> ]
// )
//
// The main file header specifies how many streams are present.  For
// each one, there must be a stream header chunk and a stream format
// chunk, enlosed in a 'strl' LIST chunk.  The 'strf' chunk contains
// type-specific format information; for a video stream, this should
// be a BITMAPINFO structure, including palette.  For an audio stream,
// this should be a WAVEFORMAT (or PCMWAVEFORMAT) structure.
//
// The actual data is contained in subchunks within the 'movi' LIST
// chunk.  The first two characters of each data chunk are the
// stream number with which that data is associated.
//
// Some defined chunk types:
// Video Streams:
// ##db:   RGB DIB bits
// ##dc:   RLE8 compressed DIB bits
// ##pc:   Palette Change
//
// Audio Streams:
// ##wb:   waveform audio bytes
//
// The grouping into LIST 'rec' chunks implies only that the contents of
// the chunk should be read into memory at the same time.  This
// grouping is used for files specifically intended to be played from
// CD-ROM.
//
// The index chunk at the end of the file should contain one entry for
// each data chunk in the file.
//
// Limitations for the current software:
// Only one video stream and one audio stream are allowed.
// The streams must start at the beginning of the file.
//
//
// To register codec types please obtain a copy of the Multimedia
// Developer Registration Kit from:
//
// Microsoft Corporation
// Multimedia Systems Group
// Product Marketing
// One Microsoft Way
// Redmond, WA 98052-6399
//

{ -- form types, list types and chunk types ----------------------------------- }

const
  formtypeAVI = $20495641; // mmioFOURCC('A', 'V', 'I', ' ')
  listtypeAVIHEADER = $6C726468; // mmioFOURCC('h', 'd', 'r', 'l')
  ckidAVIMAINHDR = $68697661; // mmioFOURCC('a', 'v', 'i', 'h')
  listtypeSTREAMHEADER = $6C727473; // mmioFOURCC('s', 't', 'r', 'l')
  ckidSTREAMHEADER = $68727473; // mmioFOURCC('s', 't', 'r', 'h')
  ckidSTREAMFORMAT = $66727473; // mmioFOURCC('s', 't', 'r', 'f')
  ckidSTREAMHANDLERDATA = $64727473; // mmioFOURCC('s', 't', 'r', 'd')
  ckidSTREAMNAME = $6E727473; // mmioFOURCC('s', 't', 'r', 'n')

  listtypeAVIMOVIE = $69766F6D; // mmioFOURCC('m', 'o', 'v', 'i')
  listtypeAVIRECORD = $20636572; // mmioFOURCC('r', 'e', 'c', ' ')

  ckidAVINEWINDEX = $31786469; // mmioFOURCC('i', 'd', 'x', '1')

  { -- Stream types for the <fccType> field of the stream header ---------------- }

  streamtypeVIDEO = $73646976; // mmioFOURCC('v', 'i', 'd', 's')
  streamtypeAUDIO = $73647561; // mmioFOURCC('a', 'u', 'd', 's')
  streamtypeMIDI = $7364696D; // mmioFOURCC('m', 'i', 'd', 's')
  streamtypeTEXT = $73747874; // mmioFOURCC('t', 'x', 't', 's')

  { -- Basic chunk types -------------------------------------------------------- }

  cktypeDIBbits = $6264; // aviTWOCC('d', 'b')
  cktypeDIBcompressed = $6364; // aviTWOCC('d', 'c')
  cktypePALchange = $6370; // aviTWOCC('p', 'c')
  cktypeWAVEbytes = $6277; // aviTWOCC('w', 'b')

  { -- Chunk id to use for extra chunks for padding ----------------------------- }

  ckidAVIPADDING = $4B4E554A; // mmioFOURCC('J', 'U', 'N', 'K')

  (*
    ** Useful macros
    **
    ** Warning: These are nasty macro, and MS C 6.0 compiles some of them
    ** incorrectly if optimizations are on.  Ack.
  *)

  { -- Macro to get stream number out of a FOURCC ckid -------------------------- }

function FromHex(n: BYTE): BYTE;
function StreamFromFOURCC(fcc: DWORD): BYTE;

{ -- Macro to get TWOCC chunk type out of a FOURCC ckid ----------------------- }

function TWOCCFromFOURCC(fcc: DWORD): word;

{ -- Macro to make a ckid for a chunk out of a TWOCC and a stream num (0-255) - }

function ToHex(n: BYTE): BYTE;
function MAKEAVICKID(tcc: word; stream: BYTE): DWORD;

{ -- Main AVI file header ----------------------------------------------------- }

{ -- flags for use in <dwFlags> in AVIFileHdr --------------------------------- }

const
  AVIF_HASINDEX = $00000010; // Index at end of file?
  AVIF_MUSTUSEINDEX = $00000020;
  AVIF_ISINTERLEAVED = $00000100;
  AVIF_TRUSTCKTYPE = $00000800; // Use CKType to find key frames?
  AVIF_WASCAPTUREFILE = $00010000;
  AVIF_COPYRIGHTED = $00020000;

  { -- The AVI File Header LIST chunk should be padded to this size ------------- }

const
  AVI_HEADERSIZE = 2048; // size of AVI header list

type
  PMainAVIHeader = ^TMainAVIHeader;

  TMainAVIHeader = packed record
    dwMicroSecPerFrame: DWORD; // frame display rate (or 0L)
    dwMaxBytesPerSec: DWORD; // max. transfer rate
    dwPaddingGranularity: DWORD; // pad to multiples of this
    // size; normally 2K.
    dwFlags: DWORD; // the ever-present flags
    dwTotalFrames: DWORD; // # frames in file
    dwInitialFrames: DWORD;
    dwStreams: DWORD;
    dwSuggestedBufferSize: DWORD;

    dwWidth: DWORD;
    dwHeight: DWORD;

    dwReserved: array [0 .. 3] of DWORD;
  end;

  { -- Stream header ------------------------------------------------------------ }

const
  AVISF_DISABLED = $00000001;

  AVISF_VIDEO_PALCHANGES = $00010000;

type
  PAVIStreamHeader = ^TAVIStreamHeader;

  TAVIStreamHeader = packed record
    fccType: FOURCC;
    fccHandler: FOURCC;
    dwFlags: DWORD; // Contains AVITF_* flags
    wPriority: word;
    wLanguage: word;
    dwInitialFrames: DWORD;
    dwScale: DWORD;
    dwRate: DWORD; // dwRate / dwScale == samples/second
    dwStart: DWORD;
    dwLength: DWORD; // In units above...
    dwSuggestedBufferSize: DWORD;
    dwQuality: DWORD;
    dwSampleSize: DWORD;
    rcFrame: TRECT;
  end;

  { -- Flags for index ---------------------------------------------------------- }

const
  AVIIF_NOTIME = $00000100; // this frame doesn't take any time
  AVIIF_COMPUSE = $0FFF0000; // these bits are for compressor use

type
  PAVIINDEXENTRY = ^TAVIINDEXENTRY;

  TAVIINDEXENTRY = packed record
    ckid: DWORD;
    dwFlags: DWORD;
    dwChunkOffset: DWORD; // Position of chunk
    dwChunkLength: DWORD; // Length of chunk
  end;

  { -- Palette change chunk (used in video streams) ----------------------------- }

  PAVIPALCHANGE = ^TAVIPALCHANGE;

  TAVIPALCHANGE = packed record
    bFirstEntry: BYTE; // first entry to change
    bNumEntries: BYTE; // # entries to change (0 if 256)
    wFlags: word; // Mostly to preserve alignment...
    peNew: array [0 .. 0] of TPALETTEENTRY; // New color specifications
  end;

  (* ***************************************************************************
    *
    *  AVIFile - routines for reading/writing standard AVI files
    *
    ************************************************************************** *)

  //
  // Ansi - Unicode thunking.
  //
  // Unicode or Ansi-only apps can call the avifile APIs.
  // any Win32 app who wants to use
  // any of the AVI COM interfaces must be UNICODE - the AVISTREAMINFO and
  // AVIFILEINFO structures used in the Info methods of these interfaces are
  // the unicode variants, and no thunking to or from ansi takes place
  // except in the AVIFILE api entrypoints.
  //
  // For Ansi/Unicode thunking: for each entrypoint or structure that
  // uses chars or strings, two versions are declared in the Win32 version,
  // ApiNameW and ApiNameA. The default name ApiName is #defined to one or
  // other of these depending on whether UNICODE is defined (during
  // compilation of the app that is including this header). The source will
  // contain ApiName and ApiNameA (with ApiName being the Win16 implementation,
  // and also #defined to ApiNameW, and ApiNameA being the thunk entrypoint).
  //

  // For GetFrame::SetFormat - use the best format for the display

const
  AVIGETFRAMEF_BESTDISPLAYFMT = 1;

  //
  // Structures used by AVIStreamInfo & AVIFileInfo.
  //
  // These are related to, but not identical to, the header chunks
  // in an AVI file.
  //

  { -- AVISTREAMINFO ------------------------------------------------------------ }

  // for Unicode/Ansi thunking we need to declare three versions of this!

type
  PAVIStreamInfoW = ^TAVIStreamInfoW;

  TAVIStreamInfoW = packed record
    fccType: DWORD;
    fccHandler: DWORD;
    dwFlags: DWORD; // Contains AVITF_* flags
    dwCaps: DWORD;
    wPriority: word;
    wLanguage: word;
    dwScale: DWORD;
    dwRate: DWORD; // dwRate / dwScale == samples/second
    dwStart: DWORD;
    dwLength: DWORD; // In units above...
    dwInitialFrames: DWORD;
    dwSuggestedBufferSize: DWORD;
    dwQuality: DWORD;
    dwSampleSize: DWORD;
    rcFrame: TRECT;
    dwEditCount: DWORD;
    dwFormatChangeCount: DWORD;
    szName: array [0 .. 63] of WideChar;
  end;

  PAVIStreamInfoA = ^TAVIStreamInfoA;

  TAVIStreamInfoA = packed record
    fccType: DWORD;
    fccHandler: DWORD;
    dwFlags: DWORD; // Contains AVITF_* flags
    dwCaps: DWORD;
    wPriority: word;
    wLanguage: word;
    dwScale: DWORD;
    dwRate: DWORD; // dwRate / dwScale == samples/second
    dwStart: DWORD;
    dwLength: DWORD; // In units above...
    dwInitialFrames: DWORD;
    dwSuggestedBufferSize: DWORD;
    dwQuality: DWORD;
    dwSampleSize: DWORD;
    rcFrame: TRECT;
    dwEditCount: DWORD;
    dwFormatChangeCount: DWORD;
    szName: array [0 .. 63] of AnsiChar;
  end;

  PAVIStreamInfo = ^TAVIStreamInfo;
{$IFDEF UNICODE}
  TAVIStreamInfo = TAVIStreamInfoW;
{$ELSE}
  TAVIStreamInfo = TAVIStreamInfoA;
{$ENDIF}

const
  AVISTREAMINFO_DISABLED = $00000001;
  AVISTREAMINFO_FORMATCHANGES = $00010000;

  { -- AVIFILEINFO -------------------------------------------------------------- }

type
  PAVIFileInfoW = ^TAVIFileInfoW;

  TAVIFileInfoW = packed record
    dwMaxBytesPerSec: DWORD; // max. transfer rate
    dwFlags: DWORD; // the ever-present flags
    dwCaps: DWORD;
    dwStreams: DWORD;
    dwSuggestedBufferSize: DWORD;

    dwWidth: DWORD;
    dwHeight: DWORD;

    dwScale: DWORD;
    dwRate: DWORD; // dwRate / dwScale == samples/second
    dwLength: DWORD;

    dwEditCount: DWORD;

    szFileType: array [0 .. 63] of WideChar;
    // descriptive string for file type?
  end;

  PAVIFileInfoA = ^TAVIFileInfoA;

  TAVIFileInfoA = packed record
    dwMaxBytesPerSec: DWORD; // max. transfer rate
    dwFlags: DWORD; // the ever-present flags
    dwCaps: DWORD;
    dwStreams: DWORD;
    dwSuggestedBufferSize: DWORD;

    dwWidth: DWORD;
    dwHeight: DWORD;

    dwScale: DWORD;
    dwRate: DWORD; // dwRate / dwScale == samples/second
    dwLength: DWORD;

    dwEditCount: DWORD;

    szFileType: array [0 .. 63] of AnsiChar;
    // descriptive string for file type?
  end;

  PAVIFileInfo = ^TAVIFileInfo;
{$IFDEF UNICODE}
  TAVIFileInfo = TAVIFileInfoW;
{$ELSE}
  TAVIFileInfo = TAVIFileInfoA;
{$ENDIF}
  { -- Flags for dwFlags -------------------------------------------------------- }

const
  AVIFILEINFO_HASINDEX = $00000010;
  AVIFILEINFO_MUSTUSEINDEX = $00000020;
  AVIFILEINFO_ISINTERLEAVED = $00000100;
  AVIFILEINFO_WASCAPTUREFILE = $00010000;
  AVIFILEINFO_COPYRIGHTED = $00020000;

  { -- Flags for dwCaps --------------------------------------------------------- }

  AVIFILECAPS_CANREAD = $00000001;
  AVIFILECAPS_CANWRITE = $00000002;
  AVIFILECAPS_ALLKEYFRAMES = $00000010;
  AVIFILECAPS_NOCOMPRESSION = $00000020;

type
  TAVISAVECALLBACK = function(i: int): BOOL; pascal;

  { -- AVICOMPRESSOPTIONS ------------------------------------------------------- }

  // Make sure it matches the AutoDoc in avisave.c !!!

type
  PAVICOMPRESSOPTIONS = ^TAVICOMPRESSOPTIONS;

  TAVICOMPRESSOPTIONS = packed record
    fccType: DWORD; // stream type, for consistency
    fccHandler: DWORD; // compressor
    dwKeyFrameEvery: DWORD; // keyframe rate
    dwQuality: DWORD; // compress quality 0-10,000
    dwBytesPerSecond: DWORD; // bytes per second
    dwFlags: DWORD; // flags... see below
    lpFormat: PVOID; // save format
    cbFormat: DWORD;
    lpParms: PVOID; // compressor options
    cbParms: DWORD;
    dwInterleaveEvery: DWORD; // for non-video streams only
  end;

  //
  // Defines for the dwFlags field of the AVICOMPRESSOPTIONS struct
  // Each of these flags determines if the appropriate field in the structure
  // (dwInterleaveEvery, dwBytesPerSecond, and dwKeyFrameEvery) is payed
  // attention to.  See the autodoc in avisave.c for details.
  //

const
  AVICOMPRESSF_INTERLEAVE = $00000001; // interleave
  AVICOMPRESSF_DATARATE = $00000002; // use a data rate
  AVICOMPRESSF_KEYFRAMES = $00000004; // use keyframes
  AVICOMPRESSF_VALID = $00000008; // has valid data?

  (* -	-	-	-	-	-	-	-	*/


    /****** AVI Stream Interface ****************************************** *)

type
  IAVIStream = interface(IUnknown)
    function Create(lParam1, lParam2: LPARAM): HResult; stdcall;
    function Info(var psi: TAVIStreamInfoW; lSize: LONG): HResult; stdcall;
    function FindSample(lPos: LONG; lFlags: LONG): LONG; stdcall;
    function ReadFormat(lPos: LONG; lpFormat: PVOID; var lpcbFormat: LONG)
      : HResult; stdcall;
    function SetFormat(lPos: LONG; lpFormat: PVOID; cbFormat: LONG)
      : HResult; stdcall;
    function Read(lStart: LONG; lSamples: LONG; lpBuffer: PVOID; cbBuffer: LONG;
      var plBytes, plSamples: LONG): HResult; stdcall;
    function Write(lStart: LONG; lSamples: LONG; lpBuffer: PVOID;
      cbBuffer: LONG; dwFlags: DWORD; var plSampWritten, plBytesWritten: LONG)
      : HResult; stdcall;
    function Delete(lStart: LONG; lSamples: LONG): HResult; stdcall;
    function ReadData(fcc: DWORD; lp: PVOID; var lpcb: LONG): HResult; stdcall;
    function WriteData(fcc: DWORD; lp: PVOID; cb: LONG): HResult; stdcall;
    function SetInfo(var lpInfo: TAVIStreamInfoW; cbInfo: LONG)
      : HResult; stdcall;
  end;

  IAVIStreaming = interface(IUnknown)
    function _Begin(lStart, lEnd: LONG; lRate: LONG): HResult; stdcall;
    function _End: HResult; stdcall;
  end;

  IAVIEditStream = interface(IUnknown)
    function Cut(var plStart, plLength: LONG; var ppResult: IAVIStream)
      : HResult; stdcall;
    function Copy(var plStart, plLength: LONG; var ppResult: IAVIStream)
      : HResult; stdcall;
    function Paste(var plPos: LONG; var plLength: LONG; pstream: IAVIStream;
      lStart, lEnd: LONG): HResult; stdcall;
    function Clone(var ppResult: IAVIStream): HResult; stdcall;
    function SetInfo(var lpInfo: TAVIStreamInfoW; cbInfo: LONG)
      : HResult; stdcall;
  end;

  { -- AVIFile ------------------------------------------------------------------ }

  IAVIFile = interface(IUnknown)
    function Info(var pfi: TAVIFileInfoW; iSize: LONG): HResult; stdcall;
    function GetStream(var ppStream: IAVIStream; fccType: DWORD; LPARAM: LONG)
      : HResult; stdcall;
    function CreateStream(var ppStream: IAVIStream; var psi: TAVIStreamInfoW)
      : HResult; stdcall;
    function WriteData(ckid: DWORD; lpData: PVOID; cbData: LONG)
      : HResult; stdcall;
    function ReadData(ckid: DWORD; lpData: PVOID; lpcbData: PLONG)
      : HResult; stdcall;
    function EndRecord: HResult; stdcall;
    function DeleteStream(fccType: DWORD; LPARAM: LONG): HResult; stdcall;
  end;

  { -- GetFrame ----------------------------------------------------------------- }

  // The functions 'BeginExtraction' and 'EndExtraction' have actually
  // the names 'Begin' and 'End', but we cannot use that identifiers for
  // obvious reasons.

  IGetFrame = interface(IUnknown)
    function GetFrame(lPos: LONG): PBITMAPINFOHEADER; stdcall;
    function BeginExtraction(lStart, lEnd, lRate: LONG): HResult; stdcall;
    function EndExtraction: HResult; stdcall;
    function SetFormat(var lpbi: TBitmapInfoHeader; lpBits: pointer;
      x, y, dx, dy: integer): HResult; stdcall;
  end;

  { -- GUIDs -------------------------------------------------------------------- }

const
  IID_IAVIFile: TGUID = (D1: $00020020; D2: $0; D3: $0;
    D4: ($C0, $0, $0, $0, $0, $0, $0, $46));
  IID_IAVIStream: TGUID = (D1: $00020021; D2: $0; D3: $0;
    D4: ($C0, $0, $0, $0, $0, $0, $0, $46));
  IID_IAVIStreaming: TGUID = (D1: $00020022; D2: $0; D3: $0;
    D4: ($C0, $0, $0, $0, $0, $0, $0, $46));
  IID_IGetFrame: TGUID = (D1: $00020023; D2: $0; D3: $0;
    D4: ($C0, $0, $0, $0, $0, $0, $0, $46));
  IID_IAVIEditStream: TGUID = (D1: $00020024; D2: $0; D3: $0;
    D4: ($C0, $0, $0, $0, $0, $0, $0, $46));

  CLSID_AVISimpleUnMarshal: TGUID = (D1: $00020009; D2: $0; D3: $0;
    D4: ($C0, $0, $0, $0, $0, $0, $0, $46));
  CLSID_AVIFile: TGUID = (D1: $00020000; D2: $0; D3: $0;
    D4: ($C0, $0, $0, $0, $0, $0, $0, $46));

  AVIFILEHANDLER_CANREAD = $0001;
  AVIFILEHANDLER_CANWRITE = $0002;
  AVIFILEHANDLER_CANACCEPTNONRGB = $0004;

  { -- Functions ---------------------------------------------------------------- }

procedure AVIFileInit; stdcall; // Call this first!
procedure AVIFileExit; stdcall;

function AVIFileAddRef(pfile: IAVIFile): ULONG; stdcall;
function AVIFileRelease(pfile: IAVIFile): ULONG; stdcall;

function AVIFileOpenA(var ppfile: IAVIFile; szFile: LPCSTR; uMode: UINT;
  lpHandler: PCLSID): HResult; stdcall;
function AVIFileOpenW(var ppfile: IAVIFile; szFile: LPCWSTR; uMode: UINT;
  lpHandler: PCLSID): HResult; stdcall;

{$IFDEF UNICODE}
function AVIFileOpen(var ppfile: IAVIFile; szFile: LPCWSTR; uMode: UINT;
  lpHandler: PCLSID): HResult; stdcall;
{$ELSE}
function AVIFileOpen(var ppfile: IAVIFile; szFile: LPCSTR; uMode: UINT;
  lpHandler: PCLSID): HResult; stdcall;
{$ENDIF}
function AVIFileInfoW(pfile: IAVIFile; var pfi: TAVIFileInfoW; lSize: LONG)
  : HResult; stdcall;
function AVIFileInfoA(pfile: IAVIFile; var pfi: TAVIFileInfoA; lSize: LONG)
  : HResult; stdcall;

function AVIFileInfo(pfile: IAVIFile; var pfi: TAVIFileInfo; lSize: LONG)
  : HResult; stdcall;

function AVIFileGetStream(pfile: IAVIFile; var ppavi: IAVIStream;
  fccType: DWORD; LPARAM: LONG): HResult; stdcall;

function AVIFileCreateStreamW(pfile: IAVIFile; var ppavi: IAVIStream;
  var psi: TAVIStreamInfoW): HResult; stdcall;
function AVIFileCreateStreamA(pfile: IAVIFile; var ppavi: IAVIStream;
  var psi: TAVIStreamInfoA): HResult; stdcall;

function AVIFileCreateStream(pfile: IAVIFile; var ppavi: IAVIStream;
  var psi: TAVIStreamInfo): HResult; stdcall;

function AVIFileWriteData(pfile: IAVIFile; ckid: DWORD; lpData: PVOID;
  cbData: LONG): HResult; stdcall;
function AVIFileReadData(pfile: IAVIFile; ckid: DWORD; lpData: PVOID;
  var lpcbData: LONG): HResult; stdcall;
function AVIFileEndRecord(pfile: IAVIFile): HResult; stdcall;

function AVIStreamAddRef(pavi: IAVIStream): ULONG; stdcall;
function AVIStreamRelease(pavi: IAVIStream): ULONG; stdcall;

function AVIStreamInfoW(pavi: IAVIStream; var psi: TAVIStreamInfoW; lSize: LONG)
  : HResult; stdcall;
function AVIStreamInfoA(pavi: IAVIStream; var psi: TAVIStreamInfoA; lSize: LONG)
  : HResult; stdcall;

function AVIStreamInfo(pavi: IAVIStream; var psi: TAVIStreamInfo; lSize: LONG)
  : HResult; stdcall;

function AVIStreamFindSample(pavi: IAVIStream; lPos: LONG; lFlags: LONG)
  : LONG; stdcall;
function AVIStreamReadFormat(pavi: IAVIStream; lPos: LONG; lpFormat: PVOID;
  lpcbFormat: PLONG): HResult; stdcall;
function AVIStreamSetFormat(pavi: IAVIStream; lPos: LONG; lpFormat: PVOID;
  cbFormat: LONG): HResult; stdcall;
function AVIStreamReadData(pavi: IAVIStream; fcc: DWORD; lp: PVOID; lpcb: PLONG)
  : HResult; stdcall;
function AVIStreamWriteData(pavi: IAVIStream; fcc: DWORD; lp: PVOID; cb: LONG)
  : HResult; stdcall;

function AVIStreamRead(pavi: IAVIStream; lStart: LONG; lSamples: LONG;
  lpBuffer: PVOID; cbBuffer: LONG; plBytes: PLONG; plSamples: PLONG)
  : HResult; stdcall;

const
  AVISTREAMREAD_CONVENIENT = -1;

function AVIStreamWrite(pavi: IAVIStream; lStart: LONG; lSamples: LONG;
  lpBuffer: PVOID; cbBuffer: LONG; dwFlags: DWORD; plSampWritten: PLONG;
  plBytesWritten: PLONG): HResult; stdcall;

// Right now, these just use AVIStreamInfo() to get information, then
// return some of it.  Can they be more efficient?

function AVIStreamStart(pavi: IAVIStream): LONG; stdcall;
function AVIStreamLength(pavi: IAVIStream): LONG; stdcall;
function AVIStreamTimeToSample(pavi: IAVIStream; lTime: LONG): LONG; stdcall;
function AVIStreamSampleToTime(pavi: IAVIStream; lSample: LONG): LONG; stdcall;

function AVIStreamBeginStreaming(pavi: IAVIStream; lStart, lEnd: LONG;
  lRate: LONG): HResult; stdcall;
function AVIStreamEndStreaming(pavi: IAVIStream): HResult; stdcall;

{ -- Helper functions for using IGetFrame ------------------------------------- }

function AVIStreamGetFrameOpen(pavi: IAVIStream; lpbiWanted: PBITMAPINFOHEADER)
  : IGetFrame; stdcall;
function AVIStreamGetFrame(pg: IGetFrame; lPos: LONG)
  : PBITMAPINFOHEADER; stdcall;
function AVIStreamGetFrameClose(pg: IGetFrame): HResult; stdcall;

// !!! We need some way to place an advise on a stream....
// STDAPI AVIStreamHasChanged   (PAVISTREAM pavi);

{ -- Shortcut function -------------------------------------------------------- }

function AVIStreamOpenFromFileA(var ppavi: IAVIStream; szFile: LPCSTR;
  fccType: DWORD; LPARAM: LONG; mode: UINT; pclsidHandler: PCLSID)
  : HResult; stdcall;
function AVIStreamOpenFromFileW(var ppavi: IAVIStream; szFile: LPCWSTR;
  fccType: DWORD; LPARAM: LONG; mode: UINT; pclsidHandler: PCLSID)
  : HResult; stdcall;

{$IFDEF UNICODE}
function AVIStreamOpenFromFile(var ppavi: IAVIStream; szFile: LPCWSTR;
  fccType: DWORD; LPARAM: LONG; mode: UINT; pclsidHandler: PCLSID)
  : HResult; stdcall;
{$ELSE}
function AVIStreamOpenFromFile(var ppavi: IAVIStream; szFile: LPCSTR;
  fccType: DWORD; LPARAM: LONG; mode: UINT; pclsidHandler: PCLSID)
  : HResult; stdcall;
{$ENDIF}
{ -- Use to create disembodied streams ---------------------------------------- }

function AVIStreamCreate(var ppavi: IAVIStream; lParam1, lParam2: LONG;
  pclsidHandler: PCLSID): HResult; stdcall;

// PHANDLER    AVIAPI AVIGetHandler         (PAVISTREAM pavi, PAVISTREAMHANDLER psh);
// PAVISTREAM  AVIAPI AVIGetStream          (PHANDLER p);

{ -- Flags for AVIStreamFindSample -------------------------------------------- }

const
  FIND_DIR = $0000000F; // direction
  FIND_NEXT = $00000001; // go forward
  FIND_PREV = $00000004; // go backward
  FIND_FROM_START = $00000008; // start at the logical beginning

  FIND_TYPE = $000000F0; // type mask
  FIND_KEY = $00000010; // find key frame.
  FIND_ANY = $00000020; // find any (non-empty) sample
  FIND_FORMAT = $00000040; // find format change

  FIND_RET = $0000F000; // return mask
  FIND_POS = $00000000; // return logical position
  FIND_LENGTH = $00001000; // return logical size
  FIND_OFFSET = $00002000; // return physical position
  FIND_SIZE = $00003000; // return physical size
  FIND_INDEX = $00004000; // return physical index position

  { -- Stuff to support backward compat. ---------------------------------------- }

function AVIStreamFindKeyFrame(var pavi: IAVIStream; lPos: LONG; lFlags: LONG)
  : DWORD; stdcall; // AVIStreamFindSample

// Non-portable: this is alias for method name
// FindKeyFrame FindSample

function AVIStreamClose(pavi: IAVIStream): ULONG; stdcall; // AVIStreamRelease
function AVIFileClose(pfile: IAVIFile): ULONG; stdcall; // AVIFileRelease
procedure AVIStreamInit; stdcall; // AVIFileInit
procedure AVIStreamExit; stdcall; // AVIFileExit

const
  SEARCH_NEAREST = FIND_PREV;
  SEARCH_BACKWARD = FIND_PREV;
  SEARCH_FORWARD = FIND_NEXT;
  SEARCH_KEY = FIND_KEY;
  SEARCH_ANY = FIND_ANY;

  { -- Helper macros ------------------------------------------------------------ }

function AVIStreamSampleToSample(pavi1, pavi2: IAVIStream; l: LONG): LONG;
function AVIStreamNextSample(pavi: IAVIStream; l: LONG): LONG;
function AVIStreamPrevSample(pavi: IAVIStream; l: LONG): LONG;
function AVIStreamNearestSample(pavi: IAVIStream; l: LONG): LONG;
function AVIStreamNextKeyFrame(pavi: IAVIStream; l: LONG): LONG;
function AVIStreamPrevKeyFrame(pavi: IAVIStream; l: LONG): LONG;
function AVIStreamNearestKeyFrame(pavi: IAVIStream; l: LONG): LONG;
function AVIStreamIsKeyFrame(pavi: IAVIStream; l: LONG): BOOL;
function AVIStreamPrevSampleTime(pavi: IAVIStream; t: LONG): LONG;
function AVIStreamNextSampleTime(pavi: IAVIStream; t: LONG): LONG;
function AVIStreamNearestSampleTime(pavi: IAVIStream; t: LONG): LONG;
function AVIStreamNextKeyFrameTime(pavi: IAVIStream; t: LONG): LONG;
function AVIStreamPrevKeyFrameTime(pavi: IAVIStream; t: LONG): LONG;
function AVIStreamNearestKeyFrameTime(pavi: IAVIStream; t: LONG): LONG;
function AVIStreamStartTime(pavi: IAVIStream): LONG;
function AVIStreamLengthTime(pavi: IAVIStream): LONG;
function AVIStreamEnd(pavi: IAVIStream): LONG;
function AVIStreamEndTime(pavi: IAVIStream): LONG;
function AVIStreamSampleSize(pavi: IAVIStream; lPos: LONG; plSize: PLONG): LONG;
function AVIStreamFormatSize(pavi: IAVIStream; lPos: LONG;
  plSize: PLONG): HResult;
function AVIStreamDataSize(pavi: IAVIStream; fcc: DWORD; plSize: PLONG)
  : HResult;

{ == AVISave routines and structures ========================================== }

const
  comptypeDIB = $20424944; // mmioFOURCC('D', 'I', 'B', ' ')

function AVIMakeCompressedStream(var ppsCompressed: IAVIStream;
  ppsSource: IAVIStream; lpOptions: PAVICOMPRESSOPTIONS; pclsidHandler: PCLSID)
  : HResult; stdcall;

// Non-portable: uses variable number of params
// EXTERN_C HRESULT CDECL AVISaveA (LPCSTR               szFile,
// CLSID FAR *pclsidHandler,
// AVISAVECALLBACK     lpfnCallback,
// int                 nStreams,
// PAVISTREAM      pfile,
// LPAVICOMPRESSOPTIONS lpOptions,
// ...);

function AVISaveVA(szFile: LPCSTR; pclsidHandler: PCLSID;
  lpfnCallback: TAVISAVECALLBACK; nStreams: int; var ppavi: IAVIStream;
  var plpOptions: PAVICOMPRESSOPTIONS): HResult; stdcall;

// Non-portable: uses variable number of params
// EXTERN_C HRESULT CDECL AVISaveW (LPCWSTR               szFile,
// CLSID FAR *pclsidHandler,
// AVISAVECALLBACK     lpfnCallback,
// int                 nStreams,
// PAVISTREAM      pfile,
// LPAVICOMPRESSOPTIONS lpOptions,
// ...);

function AVISaveVW(szFile: LPCWSTR; pclsidHandler: PCLSID;
  lpfnCallback: TAVISAVECALLBACK; nStreams: int; var ppavi: IAVIStream;
  var plpOptions: PAVICOMPRESSOPTIONS): HResult; stdcall;

// #define AVISave      AVISaveA

function AVISaveV(szFile: LPCSTR; pclsidHandler: PCLSID;
  lpfnCallback: TAVISAVECALLBACK; nStreams: int; var ppavi: IAVIStream;
  var plpOptions: PAVICOMPRESSOPTIONS): HResult; stdcall; // AVISaveVA

function AVISaveOptions(hwnd: hwnd; uiFlags: UINT; nStreams: int;
  var ppavi: IAVIStream; var plpOptions: PAVICOMPRESSOPTIONS): BOOL; stdcall;

function AVISaveOptionsFree(nStreams: int; var plpOptions: PAVICOMPRESSOPTIONS)
  : HResult; stdcall;

{ -- FLAGS FOR uiFlags -------------------------------------------------------- }

// Same as the flags for ICCompressorChoose (see compman.h)
// These determine what the compression options dialog for video streams
// will look like.

function AVIBuildFilterW(lpszFilter: LPWSTR; cbFilter: LONG; fSaving: BOOL)
  : HResult; stdcall;
function AVIBuildFilterA(lpszFilter: LPSTR; cbFilter: LONG; fSaving: BOOL)
  : HResult; stdcall;

function AVIBuildFilter(lpszFilter: LPSTR; cbFilter: LONG; fSaving: BOOL)
  : HResult; stdcall; // AVIBuildFilterA

function AVIMakeFileFromStreams(var ppfile: IAVIFile; nStreams: int;
  var papStreams: IAVIStream): HResult; stdcall;

function AVIMakeStreamFromClipboard(cfFormat: UINT; hGlobal: THandle;
  var ppStream: IAVIStream): HResult; stdcall;

{ -- Clipboard routines ------------------------------------------------------- }

function AVIPutFileOnClipboard(pf: IAVIFile): HResult; stdcall;
function AVIGetFromClipboard(var lppf: IAVIFile): HResult; stdcall;
function AVIClearClipboard: HResult; stdcall;

{ -- Editing routines --------------------------------------------------------- }

function CreateEditableStream(var ppsEditable: IAVIStream; psSource: IAVIStream)
  : HResult; stdcall;

function EditStreamCut(pavi: IAVIStream; var plStart, plLength: LONG;
  var ppResult: IAVIStream): HResult; stdcall;

function EditStreamCopy(pavi: IAVIStream; var plStart, plLength: LONG;
  var ppResult: IAVIStream): HResult; stdcall;

function EditStreamPaste(pavi: IAVIStream; var plPos, plLength: LONG;
  pstream: IAVIStream; lStart, lEnd: LONG): HResult; stdcall;

function EditStreamClone(pavi: IAVIStream; var ppResult: IAVIStream)
  : HResult; stdcall;

function EditStreamSetNameA(pavi: IAVIStream; lpszName: LPCSTR)
  : HResult; stdcall;
function EditStreamSetNameW(pavi: IAVIStream; lpszName: LPCWSTR)
  : HResult; stdcall;
function EditStreamSetInfoW(pavi: IAVIStream; lpInfo: PAVIStreamInfoW;
  cbInfo: LONG): HResult; stdcall;
function EditStreamSetInfoA(pavi: IAVIStream; lpInfo: PAVIStreamInfoA;
  cbInfo: LONG): HResult; stdcall;

function EditStreamSetInfo(pavi: IAVIStream; lpInfo: PAVIStreamInfoA;
  cbInfo: LONG): HResult; stdcall; // EditStreamSetInfoA
function EditStreamSetName(pavi: IAVIStream; lpszName: LPCSTR): HResult;
  stdcall; // EditStreamSetNameA

{ -- Error handling ----------------------------------------------------------- }

const
  AVIERR_OK = 0;

  // !!! Questions to be answered:
  // How can you get a string form of these errors?
  // Which of these errors should be replaced by errors in SCODE.H?

const
  AVIERR_UNSUPPORTED = $80044065; // MAKE_AVIERR(101)
  AVIERR_BADFORMAT = $80044066; // MAKE_AVIERR(102)
  AVIERR_MEMORY = $80044067; // MAKE_AVIERR(103)
  AVIERR_INTERNAL = $80044068; // MAKE_AVIERR(104)
  AVIERR_BADFLAGS = $80044069; // MAKE_AVIERR(105)
  AVIERR_BADPARAM = $8004406A; // MAKE_AVIERR(106)
  AVIERR_BADSIZE = $8004406B; // MAKE_AVIERR(107)
  AVIERR_BADHANDLE = $8004406C; // MAKE_AVIERR(108)
  AVIERR_FILEREAD = $8004406D; // MAKE_AVIERR(109)
  AVIERR_FILEWRITE = $8004406E; // MAKE_AVIERR(110)
  AVIERR_FILEOPEN = $8004406F; // MAKE_AVIERR(111)
  AVIERR_COMPRESSOR = $80044070; // MAKE_AVIERR(112)
  AVIERR_NOCOMPRESSOR = $80044071; // MAKE_AVIERR(113)
  AVIERR_READONLY = $80044072; // MAKE_AVIERR(114)
  AVIERR_NODATA = $80044073; // MAKE_AVIERR(115)
  AVIERR_BUFFERTOOSMALL = $80044074; // MAKE_AVIERR(116)
  AVIERR_CANTCOMPRESS = $80044075; // MAKE_AVIERR(117)
  AVIERR_USERABORT = $800440C6; // MAKE_AVIERR(198)
  AVIERR_ERROR = $800440C7; // MAKE_AVIERR(199)

  { == MCIWnd - Window class for MCI objects ==================================== }

  //
  // MCIWnd
  //
  // MCIWnd window class header file.
  //
  // the MCIWnd window class is a window class for controling MCI devices
  // MCI devices include, wave files, midi files, AVI Video, cd audio,
  // vcr, video disc, and others..
  //
  // to learn more about MCI and mci command sets see the
  // "Microsoft Multimedia Programmers's guide" in the Win31 SDK
  //
  // the easiest use of the MCIWnd class is like so:
  //
  // hwnd = MCIWndCreate(hwndParent, hInstance, 0, "chimes.wav");
  // ...
  // MCIWndPlay(hwnd);
  // MCIWndStop(hwnd);
  // MCIWndPause(hwnd);
  // ....
  // MCIWndDestroy(hwnd);
  //
  // this will create a window with a play/pause, stop and a playbar
  // and start the wave file playing.
  //
  // mciwnd.h defines macros for all the most common MCI commands, but
  // any string command can be used if needed.
  //
  // Note: unlike the mciSendString() API, no alias or file name needs
  // to be specifed, since the device to use is implied by the window handle.
  //
  // MCIWndSendString(hwnd, "setaudio stream to 2");
  //
  // (C) Copyright Microsoft Corp. 1991-1995.  All rights reserved.
  //
  // WIN32:
  //
  // MCIWnd supports both ansi and unicode interfaces. For any message that
  // takes or returns a text string, two versions of the message are defined,
  // appended with A or W for Ansi or Wide Char. The message or api itself
  // is defined to be one or other of these depending on whether you have
  // UNICODE defined in your application.
  // Thus for the api MCIWndCreate, there are in fact two apis,
  // MCIWndCreateA and MCIWndCreateW. If you call MCIWndCreate, this will be
  // re-routed to MCIWndCreateA unless UNICODE is defined when building your
  // application. In any one application, you can mix calls to the
  // Ansi and Unicode entrypoints.
  //
  // If you use SendMessage instead of the macros below such as MCIWndOpen(),
  // you will see that the messages have changed for WIN32, to support Ansi
  // and Unicode entrypoints. In particular, MCI_OPEN has been replaced by
  // MCWNDM_OPENA, or MCIWNDM_OPENW (MCIWNDM_OPEN is defined to be one or
  // other of these).
  //
  // Also, note that the WIN32 implementation of MCIWnd uses UNICODE
  // so all apis and messages supporting ANSI strings do so by mapping them
  // UNICODE strings and then calling the corresponding UNICODE entrypoint.
  //

function MCIWndSM(hwnd: hwnd; msg: UINT; wParam: wParam; LPARAM: LPARAM): DWORD;

const
  MCIWND_WINDOW_CLASS = 'MCIWndClass';

function MCIWndCreateA(hwndParent: hwnd; hInstance: HINST; dwStyle: DWORD;
  szFile: LPCSTR): hwnd; cdecl;
function MCIWndCreateW(hwndParent: hwnd; hInstance: HINST; dwStyle: DWORD;
  szFile: LPCWSTR): hwnd; cdecl;

function MCIWndCreate(hwndParent: hwnd; hInstance: HINST; dwStyle: DWORD;
  szFile: LPCSTR): hwnd; cdecl; // MCIWndCreateA

function MCIWndRegisterClass: BOOL; cdecl;

{ -- Flags for the MCIWndOpen command ----------------------------------------- }

const
  MCIWNDOPENF_NEW = $0001; // open a new file

  { -- Window styles ------------------------------------------------------------ }

  MCIWNDF_NOAUTOSIZEWINDOW = $0001; // when movie size changes
  MCIWNDF_NOPLAYBAR = $0002; // no toolbar
  MCIWNDF_NOAUTOSIZEMOVIE = $0004; // when window size changes
  MCIWNDF_NOMENU = $0008; // no popup menu from RBUTTONDOWN
  MCIWNDF_SHOWNAME = $0010; // show name in caption
  MCIWNDF_SHOWPOS = $0020; // show position in caption
  MCIWNDF_SHOWMODE = $0040; // show mode in caption
  MCIWNDF_SHOWALL = $0070; // show all

  MCIWNDF_NOTIFYMODE = $0100; // tell parent of mode change
  MCIWNDF_NOTIFYPOS = $0200; // tell parent of pos change
  MCIWNDF_NOTIFYSIZE = $0400; // tell parent of size change
  MCIWNDF_NOTIFYERROR = $1000; // tell parent of an error
  MCIWNDF_NOTIFYALL = $1F00; // tell all

  MCIWNDF_NOTIFYANSI = $0080;

  // The MEDIA notification includes a text string.
  // To receive notifications in ANSI instead of unicode set the
  // MCIWNDF_NOTIFYANSI style bit. The macro below includes this bit
  // by default unless you define UNICODE in your application.

  MCIWNDF_NOTIFYMEDIAA = $0880; // tell parent of media change
  MCIWNDF_NOTIFYMEDIAW = $0800; // tell parent of media change

  MCIWNDF_NOTIFYMEDIA = MCIWNDF_NOTIFYMEDIAA;

  MCIWNDF_RECORD = $2000; // Give a record button
  MCIWNDF_NOERRORDLG = $4000; // Show Error Dlgs for MCI cmds?
  MCIWNDF_NOOPEN = $8000; // Don't allow user to open things

  { -- Can macros --------------------------------------------------------------- }

function MCIWndCanPlay(hwnd: hwnd): BOOL;
function MCIWndCanRecord(hwnd: hwnd): BOOL;
function MCIWndCanSave(hwnd: hwnd): BOOL;
function MCIWndCanWindow(hwnd: hwnd): BOOL;
function MCIWndCanEject(hwnd: hwnd): BOOL;
function MCIWndCanConfig(hwnd: hwnd): BOOL;
function MCIWndPaletteKick(hwnd: hwnd): BOOL;

function MCIWndSave(hwnd: hwnd; szFile: LPCSTR): DWORD;
function MCIWndSaveDialog(hwnd: hwnd): DWORD;

// If you dont give a device it will use the current device....

function MCIWndNew(hwnd: hwnd; lp: PVOID): DWORD;
function MCIWndRecord(hwnd: hwnd): DWORD;
function MCIWndOpen(hwnd: hwnd; sz: LPCSTR; f: BOOL): DWORD;
function MCIWndOpenDialog(hwnd: hwnd): DWORD;
function MCIWndClose(hwnd: hwnd): DWORD;
function MCIWndPlay(hwnd: hwnd): DWORD;
function MCIWndStop(hwnd: hwnd): DWORD;
function MCIWndPause(hwnd: hwnd): DWORD;
function MCIWndResume(hwnd: hwnd): DWORD;
function MCIWndSeek(hwnd: hwnd; lPos: DWORD): DWORD;
function MCIWndEject(hwnd: hwnd): DWORD;

function MCIWndHome(hwnd: hwnd): DWORD;
function MCIWndEnd(hwnd: hwnd): DWORD;

function MCIWndGetSource(hwnd: hwnd; prc: PRECT): DWORD;
function MCIWndPutSource(hwnd: hwnd; prc: PRECT): DWORD;

function MCIWndGetDest(hwnd: hwnd; prc: PRECT): DWORD;
function MCIWndPutDest(hwnd: hwnd; prc: PRECT): DWORD;

function MCIWndPlayReverse(hwnd: hwnd): DWORD;
function MCIWndPlayFrom(hwnd: hwnd; lPos: DWORD): DWORD;
function MCIWndPlayTo(hwnd: hwnd; lPos: DWORD): DWORD;
function MCIWndPlayFromTo(hwnd: hwnd; lStart, lEnd: DWORD): DWORD;

function MCIWndGetDeviceID(hwnd: hwnd): UINT;
function MCIWndGetAlias(hwnd: hwnd): UINT;
function MCIWndGetMode(hwnd: hwnd; lp: LPSTR; len: UINT): DWORD;
function MCIWndGetPosition(hwnd: hwnd): DWORD;
function MCIWndGetPositionString(hwnd: hwnd; lp: LPSTR; len: UINT): DWORD;
function MCIWndGetStart(hwnd: hwnd): DWORD;
function MCIWndGetLength(hwnd: hwnd): DWORD;
function MCIWndGetEnd(hwnd: hwnd): DWORD;

function MCIWndStep(hwnd: hwnd; n: DWORD): DWORD;

procedure MCIWndDestroy(hwnd: hwnd);
procedure MCIWndSetZoom(hwnd: hwnd; iZoom: UINT);
function MCIWndGetZoom(hwnd: hwnd): UINT;
function MCIWndSetVolume(hwnd: hwnd; iVol: UINT): DWORD;
function MCIWndGetVolume(hwnd: hwnd): DWORD;
function MCIWndSetSpeed(hwnd: hwnd; iSpeed: UINT): DWORD;
function MCIWndGetSpeed(hwnd: hwnd): DWORD;
function MCIWndSetTimeFormat(hwnd: hwnd; lp: LPCSTR): DWORD;
function MCIWndGetTimeFormat(hwnd: hwnd; lp: LPSTR; len: UINT): DWORD;
procedure MCIWndValidateMedia(hwnd: hwnd);

procedure MCIWndSetRepeat(hwnd: hwnd; f: BOOL);
function MCIWndGetRepeat(hwnd: hwnd): BOOL;

function MCIWndUseFrames(hwnd: hwnd): DWORD;
function MCIWndUseTime(hwnd: hwnd): DWORD;

procedure MCIWndSetActiveTimer(hwnd: hwnd; active: UINT);
procedure MCIWndSetInactiveTimer(hwnd: hwnd; inactive: UINT);
procedure MCIWndSetTimers(hwnd: hwnd; active, inactive: UINT);
function MCIWndGetActiveTimer(hwnd: hwnd): UINT;
function MCIWndGetInactiveTimer(hwnd: hwnd): UINT;

function MCIWndRealize(hwnd: hwnd; fBkgnd: BOOL): DWORD;

function MCIWndSendString(hwnd: hwnd; sz: LPCSTR): DWORD;
function MCIWndReturnString(hwnd: hwnd; lp: LPSTR; len: UINT): DWORD;
function MCIWndGetError(hwnd: hwnd; lp: LPSTR; len: UINT): DWORD;

// #define MCIWndActivate(hwnd, f)     (void)MCIWndSM(hwnd, WM_ACTIVATE, (WPARAM)(BOOL)(f), 0)

function MCIWndGetPalette(hwnd: hwnd): HPALETTE;
function MCIWndSetPalette(hwnd: hwnd; hpal: HPALETTE): DWORD;

function MCIWndGetFileName(hwnd: hwnd; lp: LPSTR; len: UINT): DWORD;
function MCIWndGetDevice(hwnd: hwnd; lp: LPSTR; len: UINT): DWORD;

function MCIWndGetStyles(hwnd: hwnd): UINT;
function MCIWndChangeStyles(hwnd: hwnd; mask: UINT; value: DWORD): DWORD;

type
  PUnknown = ^IUnknown;

function MCIWndOpenInterface(hwnd: hwnd; pUnk: PUnknown): DWORD;

function MCIWndSetOwner(hwnd: hwnd; hwndP: hwnd): DWORD;

{ -- Messages an app will send to MCIWND -------------------------------------- }

// all the text-related messages are defined out of order above (they need
// to be defined before the MCIWndOpen() macros

const
  MCIWNDM_GETDEVICEID = WM_USER + 100;
  MCIWNDM_GETSTART = WM_USER + 103;
  MCIWNDM_GETLENGTH = WM_USER + 104;
  MCIWNDM_GETEND = WM_USER + 105;
  MCIWNDM_EJECT = WM_USER + 107;
  MCIWNDM_SETZOOM = WM_USER + 108;
  MCIWNDM_GETZOOM = WM_USER + 109;
  MCIWNDM_SETVOLUME = WM_USER + 110;
  MCIWNDM_GETVOLUME = WM_USER + 111;
  MCIWNDM_SETSPEED = WM_USER + 112;
  MCIWNDM_GETSPEED = WM_USER + 113;
  MCIWNDM_SETREPEAT = WM_USER + 114;
  MCIWNDM_GETREPEAT = WM_USER + 115;
  MCIWNDM_REALIZE = WM_USER + 118;
  MCIWNDM_VALIDATEMEDIA = WM_USER + 121;
  MCIWNDM_PLAYFROM = WM_USER + 122;
  MCIWNDM_PLAYTO = WM_USER + 123;
  MCIWNDM_GETPALETTE = WM_USER + 126;
  MCIWNDM_SETPALETTE = WM_USER + 127;
  MCIWNDM_SETTIMERS = WM_USER + 129;
  MCIWNDM_SETACTIVETIMER = WM_USER + 130;
  MCIWNDM_SETINACTIVETIMER = WM_USER + 131;
  MCIWNDM_GETACTIVETIMER = WM_USER + 132;
  MCIWNDM_GETINACTIVETIMER = WM_USER + 133;
  MCIWNDM_CHANGESTYLES = WM_USER + 135;
  MCIWNDM_GETSTYLES = WM_USER + 136;
  MCIWNDM_GETALIAS = WM_USER + 137;
  MCIWNDM_PLAYREVERSE = WM_USER + 139;
  MCIWNDM_GET_SOURCE = WM_USER + 140;
  MCIWNDM_PUT_SOURCE = WM_USER + 141;
  MCIWNDM_GET_DEST = WM_USER + 142;
  MCIWNDM_PUT_DEST = WM_USER + 143;
  MCIWNDM_CAN_PLAY = WM_USER + 144;
  MCIWNDM_CAN_WINDOW = WM_USER + 145;
  MCIWNDM_CAN_RECORD = WM_USER + 146;
  MCIWNDM_CAN_SAVE = WM_USER + 147;
  MCIWNDM_CAN_EJECT = WM_USER + 148;
  MCIWNDM_CAN_CONFIG = WM_USER + 149;
  MCIWNDM_PALETTEKICK = WM_USER + 150;
  MCIWNDM_OPENINTERFACE = WM_USER + 151;
  MCIWNDM_SETOWNER = WM_USER + 152;

  { -- Define both A and W messages --------------------------------------------- }

  MCIWNDM_SENDSTRINGA = WM_USER + 101;
  MCIWNDM_GETPOSITIONA = WM_USER + 102;
  MCIWNDM_GETMODEA = WM_USER + 106;
  MCIWNDM_SETTIMEFORMATA = WM_USER + 119;
  MCIWNDM_GETTIMEFORMATA = WM_USER + 120;
  MCIWNDM_GETFILENAMEA = WM_USER + 124;
  MCIWNDM_GETDEVICEA = WM_USER + 125;
  MCIWNDM_GETERRORA = WM_USER + 128;
  MCIWNDM_NEWA = WM_USER + 134;
  MCIWNDM_RETURNSTRINGA = WM_USER + 138;
  MCIWNDM_OPENA = WM_USER + 153;

  MCIWNDM_SENDSTRINGW = WM_USER + 201;
  MCIWNDM_GETPOSITIONW = WM_USER + 202;
  MCIWNDM_GETMODEW = WM_USER + 206;
  MCIWNDM_SETTIMEFORMATW = WM_USER + 219;
  MCIWNDM_GETTIMEFORMATW = WM_USER + 220;
  MCIWNDM_GETFILENAMEW = WM_USER + 224;
  MCIWNDM_GETDEVICEW = WM_USER + 225;
  MCIWNDM_GETERRORW = WM_USER + 228;
  MCIWNDM_NEWW = WM_USER + 234;
  MCIWNDM_RETURNSTRINGW = WM_USER + 238;
  MCIWNDM_OPENW = WM_USER + 252;

  { -- Map defaults to A -------------------------------------------------------- }

  MCIWNDM_SENDSTRING = MCIWNDM_SENDSTRINGA;
  MCIWNDM_GETPOSITION = MCIWNDM_GETPOSITIONA;
  MCIWNDM_GETMODE = MCIWNDM_GETMODEA;
  MCIWNDM_SETTIMEFORMAT = MCIWNDM_SETTIMEFORMATA;
  MCIWNDM_GETTIMEFORMAT = MCIWNDM_GETTIMEFORMATA;
  MCIWNDM_GETFILENAME = MCIWNDM_GETFILENAMEA;
  MCIWNDM_GETDEVICE = MCIWNDM_GETDEVICEA;
  MCIWNDM_GETERROR = MCIWNDM_GETERRORA;
  MCIWNDM_NEW = MCIWNDM_NEWA;
  MCIWNDM_RETURNSTRING = MCIWNDM_RETURNSTRINGA;
  MCIWNDM_OPEN = MCIWNDM_OPENA;

  // note that the source text for MCIWND will thus contain
  // support for eg MCIWNDM_SENDSTRING (both the 16-bit entrypoint and
  // in win32 mapped to MCIWNDM_SENDSTRINGW), and MCIWNDM_SENDSTRINGA (the
  // win32 ansi thunk).

  { -- Messages MCIWND will send to an app -------------------------------------- }

const
  MCIWNDM_NOTIFYMODE = WM_USER + 200; // wp = hwnd, lp = mode
  MCIWNDM_NOTIFYPOS = WM_USER + 201; // wp = hwnd, lp = pos
  MCIWNDM_NOTIFYSIZE = WM_USER + 202; // wp = hwnd
  MCIWNDM_NOTIFYMEDIA = WM_USER + 203; // wp = hwnd, lp = fn
  MCIWNDM_NOTIFYERROR = WM_USER + 205; // wp = hwnd, lp = error

  { -- Special seek values for START and END ------------------------------------ }

  MCIWND_START = DWORD(-1);
  MCIWND_END = DWORD(-2);

  { == VIDEO - Video capture driver interface =================================== }

type
  HVIDEO = THandle;
  PHVIDEO = ^HVIDEO;

  { -- Error return values ------------------------------------------------------ }

const
  DV_ERR_OK = 0; // No error
  DV_ERR_BASE = 1; // Error Base
  DV_ERR_NONSPECIFIC = DV_ERR_BASE;
  DV_ERR_BADFORMAT = DV_ERR_BASE + 1; // unsupported video format
  DV_ERR_STILLPLAYING = DV_ERR_BASE + 2; // still something playing
  DV_ERR_UNPREPARED = DV_ERR_BASE + 3; // header not prepared
  DV_ERR_SYNC = DV_ERR_BASE + 4; // device is synchronous
  DV_ERR_TOOMANYCHANNELS = DV_ERR_BASE + 5; // number of channels exceeded
  DV_ERR_NOTDETECTED = DV_ERR_BASE + 6; // HW not detected
  DV_ERR_BADINSTALL = DV_ERR_BASE + 7; // Can not get Profile
  DV_ERR_CREATEPALETTE = DV_ERR_BASE + 8;
  DV_ERR_SIZEFIELD = DV_ERR_BASE + 9;
  DV_ERR_PARAM1 = DV_ERR_BASE + 10;
  DV_ERR_PARAM2 = DV_ERR_BASE + 11;
  DV_ERR_CONFIG1 = DV_ERR_BASE + 12;
  DV_ERR_CONFIG2 = DV_ERR_BASE + 13;
  DV_ERR_FLAGS = DV_ERR_BASE + 14;
  DV_ERR_13 = DV_ERR_BASE + 15;

  DV_ERR_NOTSUPPORTED = DV_ERR_BASE + 16; // function not suported
  DV_ERR_NOMEM = DV_ERR_BASE + 17; // out of memory
  DV_ERR_ALLOCATED = DV_ERR_BASE + 18; // device is allocated
  DV_ERR_BADDEVICEID = DV_ERR_BASE + 19;
  DV_ERR_INVALHANDLE = DV_ERR_BASE + 20;
  DV_ERR_BADERRNUM = DV_ERR_BASE + 21;
  DV_ERR_NO_BUFFERS = DV_ERR_BASE + 22; // out of buffers

  DV_ERR_MEM_CONFLICT = DV_ERR_BASE + 23; // Mem conflict detected
  DV_ERR_IO_CONFLICT = DV_ERR_BASE + 24; // I/O conflict detected
  DV_ERR_DMA_CONFLICT = DV_ERR_BASE + 25; // DMA conflict detected
  DV_ERR_INT_CONFLICT = DV_ERR_BASE + 26; // Interrupt conflict detected
  DV_ERR_PROTECT_ONLY = DV_ERR_BASE + 27; // Can not run in standard mode
  DV_ERR_LASTERROR = DV_ERR_BASE + 27;

  DV_ERR_USER_MSG = DV_ERR_BASE + 1000; // Hardware specific errors

  { -- Callback messages -------------------------------------------------------- }

  // Note that the values for all installable driver callback messages are
  // identical, (ie. MM_DRVM_DATA has the same value for capture drivers,
  // installable video codecs, and the audio compression manager).

const
  DV_VM_OPEN = MM_DRVM_OPEN; // Obsolete messages
  DV_VM_CLOSE = MM_DRVM_CLOSE;
  DV_VM_DATA = MM_DRVM_DATA;
  DV_VM_ERROR = MM_DRVM_ERROR;

  { == Structures =============================================================== }

  { -- Video data block header -------------------------------------------------- }

type
  PVIDEOHDR = ^TVIDEOHDR;

  TVIDEOHDR = record
    lpData: PBYTE; // pointer to locked data buffer
    dwBufferLength: DWORD; // Length of data buffer
    dwBytesUsed: DWORD; // Bytes actually used
    dwTimeCaptured: DWORD; // Milliseconds from start of stream
    dwUser: DWORD; // for client's use
    dwFlags: DWORD; // assorted flags (see defines)
    dwReserved: array [0 .. 3] of DWORD; // reserved for driver
  end;

  { -- dwFlags field of VIDEOHDR ------------------------------------------------ }

const
  VHDR_DONE = $00000001; // Done bit
  VHDR_PREPARED = $00000002; // Set if this header has been prepared
  VHDR_INQUEUE = $00000004; // Reserved for driver
  VHDR_KEYFRAME = $00000008; // Key Frame

  { -- Channel capabilities structure ------------------------------------------- }

type
  PCHANNEL_CAPS = ^TCHANNEL_CAPS;

  TCHANNEL_CAPS = record
    dwFlags: DWORD; // Capability flags
    dwSrcRectXMod: DWORD; // Granularity of src rect in x
    dwSrcRectYMod: DWORD; // Granularity of src rect in y
    dwSrcRectWidthMod: DWORD; // Granularity of src rect width
    dwSrcRectHeightMod: DWORD; // Granularity of src rect height
    dwDstRectXMod: DWORD; // Granularity of dst rect in x
    dwDstRectYMod: DWORD; // Granularity of dst rect in y
    dwDstRectWidthMod: DWORD; // Granularity of dst rect width
    dwDstRectHeightMod: DWORD; // Granularity of dst rect height
  end;

  { -- dwFlags of CHANNEL_CAPS -------------------------------------------------- }

const
  VCAPS_OVERLAY = $00000001; // overlay channel
  VCAPS_SRC_CAN_CLIP = $00000002; // src rect can clip
  VCAPS_DST_CAN_CLIP = $00000004; // dst rect can clip
  VCAPS_CAN_SCALE = $00000008; // allows src != dst

  { == API flags ================================================================ }

  { -- Types of channels to open with the videoOpen function -------------------- }

const
  VIDEO_EXTERNALIN = $0001;
  VIDEO_EXTERNALOUT = $0002;
  VIDEO_IN = $0004;
  VIDEO_OUT = $0008;

  { -- Is a driver dialog available for this channel ---------------------------- }

  VIDEO_DLG_QUERY = $0010;

  { -- videoConfigure (both GET and SET) ---------------------------------------- }

  VIDEO_CONFIGURE_QUERY = $8000;

  { -- videoConfigure (SET only) ------------------------------------------------ }

  VIDEO_CONFIGURE_SET = $1000;

  { -- videoConfigure (GET only) ------------------------------------------------ }

  VIDEO_CONFIGURE_GET = $2000;
  VIDEO_CONFIGURE_QUERYSIZE = $0001;

  VIDEO_CONFIGURE_CURRENT = $0010;
  VIDEO_CONFIGURE_NOMINAL = $0020;
  VIDEO_CONFIGURE_MIN = $0040;
  VIDEO_CONFIGURE_MAX = $0080;

  { == Configure messages ======================================================= }

  DVM_USER = $4000;

  DVM_CONFIGURE_START = $1000;
  DVM_CONFIGURE_END = $1FFF;

  DVM_PALETTE = DVM_CONFIGURE_START + 1;
  DVM_FORMAT = DVM_CONFIGURE_START + 2;
  DVM_PALETTERGB555 = DVM_CONFIGURE_START + 3;
  DVM_SRC_RECT = DVM_CONFIGURE_START + 4;
  DVM_DST_RECT = DVM_CONFIGURE_START + 5;

  { == AVICAP - Window class for AVI capture ==================================== }

function AVICapSM(hwnd: hwnd; m: UINT; w: wParam; l: LPARAM): DWORD;

{ -- Window messages WM_CAP... which can be sent to an AVICAP window ---------- }

// UNICODE
//
// The Win32 version of AVICAP on NT supports UNICODE applications:
// for each API or message that takes a char or string parameter, there are
// two versions, ApiNameA and ApiNameW. The default name ApiName is #defined
// to one or other depending on whether UNICODE is defined. Apps can call
// the A and W apis directly, and mix them.
//
// The 32-bit AVICAP on NT uses unicode exclusively internally.
// ApiNameA() will be implemented as a call to ApiNameW() together with
// translation of strings.

// Defines start of the message range
const
  WM_CAP_START = WM_USER;
  WM_CAP_UNICODE_START = WM_USER + 100;

  WM_CAP_GET_CAPSTREAMPTR = WM_CAP_START + 1;

  WM_CAP_SET_CALLBACK_ERRORW = WM_CAP_UNICODE_START + 2;
  WM_CAP_SET_CALLBACK_STATUSW = WM_CAP_UNICODE_START + 3;
  WM_CAP_SET_CALLBACK_ERRORA = WM_CAP_START + 2;
  WM_CAP_SET_CALLBACK_STATUSA = WM_CAP_START + 3;
  WM_CAP_SET_CALLBACK_ERROR = WM_CAP_SET_CALLBACK_ERRORA;
  WM_CAP_SET_CALLBACK_STATUS = WM_CAP_SET_CALLBACK_STATUSA;

  WM_CAP_SET_CALLBACK_YIELD = WM_CAP_START + 4;
  WM_CAP_SET_CALLBACK_FRAME = WM_CAP_START + 5;
  WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_CAP_START + 6;
  WM_CAP_SET_CALLBACK_WAVESTREAM = WM_CAP_START + 7;
  WM_CAP_GET_USER_DATA = WM_CAP_START + 8;
  WM_CAP_SET_USER_DATA = WM_CAP_START + 9;

  WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10;
  WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11;

  WM_CAP_DRIVER_GET_NAMEA = WM_CAP_START + 12;
  WM_CAP_DRIVER_GET_VERSIONA = WM_CAP_START + 13;
  WM_CAP_DRIVER_GET_NAMEW = WM_CAP_UNICODE_START + 12;
  WM_CAP_DRIVER_GET_VERSIONW = WM_CAP_UNICODE_START + 13;
  WM_CAP_DRIVER_GET_NAME = WM_CAP_DRIVER_GET_NAMEA;
  WM_CAP_DRIVER_GET_VERSION = WM_CAP_DRIVER_GET_VERSIONA;

  WM_CAP_DRIVER_GET_CAPS = WM_CAP_START + 14;

  WM_CAP_FILE_SET_CAPTURE_FILEA = WM_CAP_START + 20;
  WM_CAP_FILE_GET_CAPTURE_FILEA = WM_CAP_START + 21;
  WM_CAP_FILE_SAVEASA = WM_CAP_START + 23;
  WM_CAP_FILE_SAVEDIBA = WM_CAP_START + 25;
  WM_CAP_FILE_SET_CAPTURE_FILEW = WM_CAP_UNICODE_START + 20;
  WM_CAP_FILE_GET_CAPTURE_FILEW = WM_CAP_UNICODE_START + 21;
  WM_CAP_FILE_SAVEASW = WM_CAP_UNICODE_START + 23;
  WM_CAP_FILE_SAVEDIBW = WM_CAP_UNICODE_START + 25;
  WM_CAP_FILE_SET_CAPTURE_FILE = WM_CAP_FILE_SET_CAPTURE_FILEA;
  WM_CAP_FILE_GET_CAPTURE_FILE = WM_CAP_FILE_GET_CAPTURE_FILEA;
  WM_CAP_FILE_SAVEAS = WM_CAP_FILE_SAVEASA;
  WM_CAP_FILE_SAVEDIB = WM_CAP_FILE_SAVEDIBA;

  // out of order to save on ifdefs

  WM_CAP_FILE_ALLOCATE = WM_CAP_START + 22;
  WM_CAP_FILE_SET_INFOCHUNK = WM_CAP_START + 24;

  WM_CAP_EDIT_COPY = WM_CAP_START + 30;

  WM_CAP_SET_AUDIOFORMAT = WM_CAP_START + 35;
  WM_CAP_GET_AUDIOFORMAT = WM_CAP_START + 36;

  WM_CAP_DLG_VIDEOFORMAT = WM_CAP_START + 41;
  WM_CAP_DLG_VIDEOSOURCE = WM_CAP_START + 42;
  WM_CAP_DLG_VIDEODISPLAY = WM_CAP_START + 43;
  WM_CAP_GET_VIDEOFORMAT = WM_CAP_START + 44;
  WM_CAP_SET_VIDEOFORMAT = WM_CAP_START + 45;
  WM_CAP_DLG_VIDEOCOMPRESSION = WM_CAP_START + 46;

  WM_CAP_SET_PREVIEW = WM_CAP_START + 50;
  WM_CAP_SET_OVERLAY = WM_CAP_START + 51;
  WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52;
  WM_CAP_SET_SCALE = WM_CAP_START + 53;
  WM_CAP_GET_STATUS = WM_CAP_START + 54;
  WM_CAP_SET_SCROLL = WM_CAP_START + 55;

  WM_CAP_GRAB_FRAME = WM_CAP_START + 60;
  WM_CAP_GRAB_FRAME_NOSTOP = WM_CAP_START + 61;

  WM_CAP_SEQUENCE = WM_CAP_START + 62;
  WM_CAP_SEQUENCE_NOFILE = WM_CAP_START + 63;
  WM_CAP_SET_SEQUENCE_SETUP = WM_CAP_START + 64;
  WM_CAP_GET_SEQUENCE_SETUP = WM_CAP_START + 65;

  WM_CAP_SET_MCI_DEVICEA = WM_CAP_START + 66;
  WM_CAP_GET_MCI_DEVICEA = WM_CAP_START + 67;
  WM_CAP_SET_MCI_DEVICEW = WM_CAP_UNICODE_START + 66;
  WM_CAP_GET_MCI_DEVICEW = WM_CAP_UNICODE_START + 67;
  WM_CAP_SET_MCI_DEVICE = WM_CAP_SET_MCI_DEVICEA;
  WM_CAP_GET_MCI_DEVICE = WM_CAP_GET_MCI_DEVICEA;

  WM_CAP_STOP = WM_CAP_START + 68;
  WM_CAP_ABORT = WM_CAP_START + 69;

  WM_CAP_SINGLE_FRAME_OPEN = WM_CAP_START + 70;
  WM_CAP_SINGLE_FRAME_CLOSE = WM_CAP_START + 71;
  WM_CAP_SINGLE_FRAME = WM_CAP_START + 72;

  WM_CAP_PAL_OPENA = WM_CAP_START + 80;
  WM_CAP_PAL_SAVEA = WM_CAP_START + 81;
  WM_CAP_PAL_OPENW = WM_CAP_UNICODE_START + 80;
  WM_CAP_PAL_SAVEW = WM_CAP_UNICODE_START + 81;
  WM_CAP_PAL_OPEN = WM_CAP_PAL_OPENA;
  WM_CAP_PAL_SAVE = WM_CAP_PAL_SAVEA;

  WM_CAP_PAL_PASTE = WM_CAP_START + 82;
  WM_CAP_PAL_AUTOCREATE = WM_CAP_START + 83;
  WM_CAP_PAL_MANUALCREATE = WM_CAP_START + 84;

  // Following added post VFW 1.1

  WM_CAP_SET_CALLBACK_CAPCONTROL = WM_CAP_START + 85;

  // Defines end of the message range

  WM_CAP_UNICODE_END = WM_CAP_PAL_SAVEW;
  WM_CAP_END = WM_CAP_UNICODE_END;

  { -- Callback definitions ----------------------------------------------------- }

type
  TCAPYIELDCALLBACK = function(hwnd: hwnd): DWORD; stdcall;

  TCAPSTATUSCALLBACKW = function(hwnd: hwnd; nID: int; lpsz: LPCWSTR)
    : DWORD; stdcall;
  TCAPERRORCALLBACKW = function(hwnd: hwnd; nID: int; lpsz: LPCWSTR)
    : DWORD; stdcall;
  TCAPSTATUSCALLBACKA = function(hwnd: hwnd; nID: int; lpsz: LPCSTR)
    : DWORD; stdcall;
  TCAPERRORCALLBACKA = function(hwnd: hwnd; nID: int; lpsz: LPCSTR)
    : DWORD; stdcall;

  TCAPSTATUSCALLBACK = TCAPSTATUSCALLBACKA;
  TCAPERRORCALLBACK = TCAPERRORCALLBACKA;

  TCAPVIDEOCALLBACK = function(hwnd: hwnd; lpVHdr: PVIDEOHDR): DWORD; stdcall;
  TCAPWAVECALLBACK = function(hwnd: hwnd; lpWHdr: PWAVEHDR): DWORD; stdcall;
  TCAPCONTROLCALLBACK = function(hwnd: hwnd; nState: int): DWORD; stdcall;

  { -- Structures --------------------------------------------------------------- }

type
  PCAPDRIVERCAPS = ^TCAPDRIVERCAPS;

  TCAPDRIVERCAPS = record
    wDeviceIndex: UINT; // Driver index in system.ini
    fHasOverlay: BOOL; // Can device overlay?
    fHasDlgVideoSource: BOOL; // Has Video source dlg?
    fHasDlgVideoFormat: BOOL; // Has Format dlg?
    fHasDlgVideoDisplay: BOOL; // Has External out dlg?
    fCaptureInitialized: BOOL; // Driver ready to capture?
    fDriverSuppliesPalettes: BOOL; // Can driver make palettes?

    // following always NULL on Win32.
    hVideoIn: THandle; // Driver In channel
    hVideoOut: THandle; // Driver Out channel
    hVideoExtIn: THandle; // Driver Ext In channel
    hVideoExtOut: THandle; // Driver Ext Out channel
  end;

  PCAPSTATUS = ^TCAPSTATUS;

  TCAPSTATUS = record
    uiImageWidth: UINT; // Width of the image
    uiImageHeight: UINT; // Height of the image
    fLiveWindow: BOOL; // Now Previewing video?
    fOverlayWindow: BOOL; // Now Overlaying video?
    fScale: BOOL; // Scale image to client?
    ptScroll: TPOINT; // Scroll position
    fUsingDefaultPalette: BOOL; // Using default driver palette?
    fAudioHardware: BOOL; // Audio hardware present?
    fCapFileExists: BOOL; // Does capture file exist?
    dwCurrentVideoFrame: DWORD; // # of video frames cap'td
    dwCurrentVideoFramesDropped: DWORD; // # of video frames dropped
    dwCurrentWaveSamples: DWORD; // # of wave samples cap'td
    dwCurrentTimeElapsedMS: DWORD; // Elapsed capture duration
    hPalCurrent: HPALETTE; // Current palette in use
    fCapturingNow: BOOL; // Capture in progress?
    dwReturn: DWORD; // Error value after any operation
    wNumVideoAllocated: UINT; // Actual number of video buffers
    wNumAudioAllocated: UINT; // Actual number of audio buffers
  end;

  // Default values in parenthesis

  PCAPTUREPARMS = ^TCAPTUREPARMS;

  TCAPTUREPARMS = record
    dwRequestMicroSecPerFrame: DWORD; // Requested capture rate
    fMakeUserHitOKToCapture: BOOL; // Show "Hit OK to cap" dlg?
    wPercentDropForError: UINT; // Give error msg if > (10%)
    fYield: BOOL; // Capture via background task?
    dwIndexSize: DWORD; // Max index size in frames (32K)
    wChunkGranularity: UINT; // Junk chunk granularity (2K)
    fUsingDOSMemory: BOOL; // Use DOS buffers?
    wNumVideoRequested: UINT; // # video buffers, If 0, autocalc
    fCaptureAudio: BOOL; // Capture audio?
    wNumAudioRequested: UINT; // # audio buffers, If 0, autocalc
    vKeyAbort: UINT; // Virtual key causing abort
    fAbortLeftMouse: BOOL; // Abort on left mouse?
    fAbortRightMouse: BOOL; // Abort on right mouse?
    fLimitEnabled: BOOL; // Use wTimeLimit?
    wTimeLimit: UINT; // Seconds to capture
    fMCIControl: BOOL; // Use MCI video source?
    fStepMCIDevice: BOOL; // Step MCI device?
    dwMCIStartTime: DWORD; // Time to start in MS
    dwMCIStopTime: DWORD; // Time to stop in MS
    fStepCaptureAt2x: BOOL; // Perform spatial averaging 2x
    wStepCaptureAverageFrames: UINT; // Temporal average n Frames
    dwAudioBufferSize: DWORD; // Size of audio bufs (0 = default)
    fDisableWriteCache: BOOL; // Attempt to disable write cache
    AVStreamMaster: UINT; // Which stream controls length?
  end;

  { -- AVStreamMaster ----------------------------------------------------------- }

  // Since Audio and Video streams generally use non-synchronized capture
  // clocks, this flag determines whether the audio stream is to be considered
  // the master or controlling clock when writing the AVI file:
  //
  // AVSTREAMMASTER_AUDIO  - Audio is master, video frame duration is forced
  // to match audio duration (VFW 1.0, 1.1 default)
  // AVSTREAMMASTER_NONE   - No master, audio and video streams may be of
  // different lengths

const
  AVSTREAMMASTER_AUDIO = 0; // Audio master (VFW 1.0, 1.1)
  AVSTREAMMASTER_NONE = 1; // No master

type
  PCAPINFOCHUNK = ^TCAPINFOCHUNK;

  TCAPINFOCHUNK = record
    fccInfoID: FOURCC; // Chunk ID, "ICOP" for copyright
    lpData: PVOID; // pointer to data
    cbData: DWORD; // size of lpData
  end;

  { -- CapControlCallback states ------------------------------------------------ }

const
  CONTROLCALLBACK_PREROLL = 1; // Waiting to start capture
  CONTROLCALLBACK_CAPTURING = 2; // Now capturing

  { -- Message crackers for above ----------------------------------------------- }

  // message wrapper macros are defined for the default messages only. Apps
  // that wish to mix Ansi and UNICODE message sending will have to
  // reference the _A and _W messages directly

function capSetCallbackOnError(hwnd: hwnd; fpProc: TCAPERRORCALLBACK): BOOL;
function capSetCallbackOnStatus(hwnd: hwnd; fpProc: TCAPSTATUSCALLBACK): BOOL;
function capSetCallbackOnYield(hwnd: hwnd; fpProc: TCAPYIELDCALLBACK): BOOL;
function capSetCallbackOnFrame(hwnd: hwnd; fpProc: TCAPVIDEOCALLBACK): BOOL;
function capSetCallbackOnVideoStream(hwnd: hwnd;
  fpProc: TCAPVIDEOCALLBACK): BOOL;
function capSetCallbackOnWaveStream(hwnd: hwnd; fpProc: TCAPWAVECALLBACK): BOOL;
function capSetCallbackOnCapControl(hwnd: hwnd;
  fpProc: TCAPCONTROLCALLBACK): BOOL;

function capSetUserData(hwnd: hwnd; lUser: DWORD): BOOL;
function capGetUserData(hwnd: hwnd): DWORD;

function capDriverConnect(hwnd: hwnd; i: int): BOOL;
function capDriverDisconnect(hwnd: hwnd): BOOL;
function capDriverGetName(hwnd: hwnd; szName: LPSTR; wSize: word): BOOL;
function capDriverGetVersion(hwnd: hwnd; szVer: LPSTR; wSize: word): BOOL;
function capDriverGetCaps(hwnd: hwnd; s: PCAPDRIVERCAPS; wSize: word): BOOL;

function capFileSetCaptureFile(hwnd: hwnd; szName: LPCSTR): BOOL;
function capFileGetCaptureFile(hwnd: hwnd; szName: LPSTR; wSize: word): BOOL;
function capFileAlloc(hwnd: hwnd; dwSize: DWORD): BOOL;
function capFileSaveAs(hwnd: hwnd; szName: LPCSTR): BOOL;
function capFileSetInfoChunk(hwnd: hwnd; lpInfoChunk: PCAPINFOCHUNK): BOOL;
function capFileSaveDIB(hwnd: hwnd; szName: LPCSTR): BOOL;

function capEditCopy(hwnd: hwnd): BOOL;

function capSetAudioFormat(hwnd: hwnd; s: PWAVEFORMATEX; wSize: word): BOOL;
function capGetAudioFormat(hwnd: hwnd; s: PWAVEFORMATEX; wSize: word): DWORD;
function capGetAudioFormatSize(hwnd: hwnd): DWORD;

function capDlgVideoFormat(hwnd: hwnd): BOOL;
function capDlgVideoSource(hwnd: hwnd): BOOL;
function capDlgVideoDisplay(hwnd: hwnd): BOOL;
function capDlgVideoCompression(hwnd: hwnd): BOOL;

function capGetVideoFormat(hwnd: hwnd; s: PVOID; wSize: word): DWORD;
function capGetVideoFormatSize(hwnd: hwnd): DWORD;
function capSetVideoFormat(hwnd: hwnd; s: PVOID; wSize: word): BOOL;

function capPreview(hwnd: hwnd; f: BOOL): BOOL;
function capPreviewRate(hwnd: hwnd; wMS: word): BOOL;
function capOverlay(hwnd: hwnd; f: BOOL): BOOL;
function capPreviewScale(hwnd: hwnd; f: BOOL): BOOL;
function capGetStatus(hwnd: hwnd; s: PCAPSTATUS; wSize: word): BOOL;
function capSetScrollPos(hwnd: hwnd; lpP: PPOINT): BOOL;

function capGrabFrame(hwnd: hwnd): BOOL;
function capGrabFrameNoStop(hwnd: hwnd): BOOL;

function capCaptureSequence(hwnd: hwnd): BOOL;
function capCaptureSequenceNoFile(hwnd: hwnd): BOOL;
function capCaptureStop(hwnd: hwnd): BOOL;
function capCaptureAbort(hwnd: hwnd): BOOL;

function capCaptureSingleFrameOpen(hwnd: hwnd): BOOL;
function capCaptureSingleFrameClose(hwnd: hwnd): BOOL;
function capCaptureSingleFrame(hwnd: hwnd): BOOL;

function capCaptureGetSetup(hwnd: hwnd; s: PCAPTUREPARMS; wSize: word): BOOL;
function capCaptureSetSetup(hwnd: hwnd; s: PCAPTUREPARMS; wSize: word): BOOL;

function capSetMCIDeviceName(hwnd: hwnd; szName: LPCSTR): BOOL;
function capGetMCIDeviceName(hwnd: hwnd; szName: LPSTR; wSize: word): BOOL;

function capPaletteOpen(hwnd: hwnd; szName: LPCSTR): BOOL;
function capPaletteSave(hwnd: hwnd; szName: LPCSTR): BOOL;
function capPalettePaste(hwnd: hwnd): BOOL;
function capPaletteAuto(hwnd: hwnd; iFrames, iColors: int): BOOL;
function capPaletteManual(hwnd: hwnd; fGrab: BOOL; iColors: int): BOOL;

{ -- The only exported functions from AVICAP.DLL ------------------------------ }

function capCreateCaptureWindowA(lpszWindowName: LPCSTR; dwStyle: DWORD;
  x, y: int; nWidth, nHeight: int; hwndParent: hwnd; nID: int): hwnd; stdcall;

function capGetDriverDescriptionA(wDriverIndex: UINT; lpszName: LPSTR;
  cbName: int; lpszVer: LPSTR; cbVer: int): BOOL; stdcall;

function capCreateCaptureWindowW(lpszWindowName: LPCWSTR; dwStyle: DWORD;
  x, y: int; nWidth, nHeight: int; hwndParent: hwnd; nID: int): hwnd; stdcall;

function capGetDriverDescriptionW(wDriverIndex: UINT; lpszName: LPWSTR;
  cbName: int; lpszVer: LPWSTR; cbVer: int): BOOL; stdcall;

function capCreateCaptureWindow(lpszWindowName: LPCSTR; dwStyle: DWORD;
  x, y: int; nWidth, nHeight: int; hwndParent: hwnd; nID: int): hwnd; stdcall;
// capCreateCaptureWindowA

function capGetDriverDescription(wDriverIndex: UINT; lpszName: LPSTR;
  cbName: int; lpszVer: LPSTR; cbVer: int): BOOL; stdcall;
// capGetDriverDescriptionA

{ -- New information chunk IDs ------------------------------------------------ }

const
  infotypeDIGITIZATION_TIME = $54494449; // mmioFOURCC ('I','D','I','T')
  infotypeSMPTE_TIME = $504D5349; // mmioFOURCC ('I','S','M','P')

  { -- String IDs from status and error callbacks ------------------------------- }

  IDS_CAP_BEGIN = 300; // "Capture Start"
  IDS_CAP_END = 301; // "Capture End"

  IDS_CAP_INFO = 401; // "%s"
  IDS_CAP_OUTOFMEM = 402; // "Out of memory"
  IDS_CAP_FILEEXISTS = 403; // "File '%s' exists -- overwrite it?"
  IDS_CAP_ERRORPALOPEN = 404; // "Error opening palette '%s'"
  IDS_CAP_ERRORPALSAVE = 405; // "Error saving palette '%s'"
  IDS_CAP_ERRORDIBSAVE = 406; // "Error saving frame '%s'"
  IDS_CAP_DEFAVIEXT = 407; // "avi"
  IDS_CAP_DEFPALEXT = 408; // "pal"
  IDS_CAP_CANTOPEN = 409; // "Cannot open '%s'"
  IDS_CAP_SEQ_MSGSTART = 410;
  // "Select OK to start capture\nof video sequence\nto %s."
  IDS_CAP_SEQ_MSGSTOP = 411; // "Hit ESCAPE or click to end capture"

  IDS_CAP_VIDEDITERR = 412; // "An error occurred while trying to run VidEdit."
  IDS_CAP_READONLYFILE = 413; // "The file '%s' is a read-only file."
  IDS_CAP_WRITEERROR = 414;
  // "Unable to write to file '%s'.\nDisk may be full."
  IDS_CAP_NODISKSPACE = 415;
  // "There is no space to create a capture file on the specified device."
  IDS_CAP_SETFILESIZE = 416; // "Set File Size"
  IDS_CAP_SAVEASPERCENT = 417; // "SaveAs: %2ld%%  Hit Escape to abort."

  IDS_CAP_DRIVER_ERROR = 418; // Driver specific error message

  IDS_CAP_WAVE_OPEN_ERROR = 419;
  // "Error: Cannot open the wave input device.\nCheck sample size, frequency, and channels."
  IDS_CAP_WAVE_ALLOC_ERROR = 420; // "Error: Out of memory for wave buffers."
  IDS_CAP_WAVE_PREPARE_ERROR = 421; // "Error: Cannot prepare wave buffers."
  IDS_CAP_WAVE_ADD_ERROR = 422; // "Error: Cannot add wave buffers."
  IDS_CAP_WAVE_SIZE_ERROR = 423; // "Error: Bad wave size."

  IDS_CAP_VIDEO_OPEN_ERROR = 424;
  // "Error: Cannot open the video input device."
  IDS_CAP_VIDEO_ALLOC_ERROR = 425; // "Error: Out of memory for video buffers."
  IDS_CAP_VIDEO_PREPARE_ERROR = 426; // "Error: Cannot prepare video buffers."
  IDS_CAP_VIDEO_ADD_ERROR = 427; // "Error: Cannot add video buffers."
  IDS_CAP_VIDEO_SIZE_ERROR = 428; // "Error: Bad video size."

  IDS_CAP_FILE_OPEN_ERROR = 429; // "Error: Cannot open capture file."
  IDS_CAP_FILE_WRITE_ERROR = 430;
  // "Error: Cannot write to capture file.  Disk may be full."
  IDS_CAP_RECORDING_ERROR = 431;
  // "Error: Cannot write to capture file.  Data rate too high or disk full."
  IDS_CAP_RECORDING_ERROR2 = 432; // "Error while recording"
  IDS_CAP_AVI_INIT_ERROR = 433; // "Error: Unable to initialize for capture."
  IDS_CAP_NO_FRAME_CAP_ERROR = 434;
  // "Warning: No frames captured.\nConfirm that vertical sync interrupts\nare configured and enabled."
  IDS_CAP_NO_PALETTE_WARN = 435; // "Warning: Using default palette."
  IDS_CAP_MCI_CONTROL_ERROR = 436; // "Error: Unable to access MCI device."
  IDS_CAP_MCI_CANT_STEP_ERROR = 437; // "Error: Unable to step MCI device."
  IDS_CAP_NO_AUDIO_CAP_ERROR = 438;
  // "Error: No audio data captured.\nCheck audio card settings."
  IDS_CAP_AVI_DRAWDIB_ERROR = 439; // "Error: Unable to draw this data format."
  IDS_CAP_COMPRESSOR_ERROR = 440; // "Error: Unable to initialize compressor."
  IDS_CAP_AUDIO_DROP_ERROR = 441;
  // "Error: Audio data was lost during capture, reduce capture rate."

  { -- Status string IDs -------------------------------------------------------- }

  IDS_CAP_STAT_LIVE_MODE = 500; // "Live window"
  IDS_CAP_STAT_OVERLAY_MODE = 501; // "Overlay window"
  IDS_CAP_STAT_CAP_INIT = 502; // "Setting up for capture - Please wait"
  IDS_CAP_STAT_CAP_FINI = 503; // "Finished capture, now writing frame %ld"
  IDS_CAP_STAT_PALETTE_BUILD = 504; // "Building palette map"
  IDS_CAP_STAT_OPTPAL_BUILD = 505; // "Computing optimal palette"
  IDS_CAP_STAT_I_FRAMES = 506; // "%d frames"
  IDS_CAP_STAT_L_FRAMES = 507; // "%ld frames"
  IDS_CAP_STAT_CAP_L_FRAMES = 508; // "Captured %ld frames"
  IDS_CAP_STAT_CAP_AUDIO = 509; // "Capturing audio"
  IDS_CAP_STAT_VIDEOCURRENT = 510;
  // "Captured %ld frames (%ld dropped) %d.%03d sec."
  IDS_CAP_STAT_VIDEOAUDIO = 511;
  // "Captured %d.%03d sec.  %ld frames (%ld dropped) (%d.%03d fps).  %ld audio bytes (%d,%03d sps)"
  IDS_CAP_STAT_VIDEOONLY = 512;
  // "Captured %d.%03d sec.  %ld frames (%ld dropped) (%d.%03d fps)"
  IDS_CAP_STAT_FRAMESDROPPED = 513;
  // "Dropped %ld of %ld frames (%d.%02d%%) during capture."

  { == FilePreview dialog ======================================================= }

function GetOpenFileNamePreviewA(lpofn: POPENFILENAMEA): BOOL; stdcall;
function GetSaveFileNamePreviewA(lpofn: POPENFILENAMEA): BOOL; stdcall;

function GetOpenFileNamePreviewW(lpofn: POPENFILENAMEW): BOOL; stdcall;
function GetSaveFileNamePreviewW(lpofn: POPENFILENAMEW): BOOL; stdcall;

function GetOpenFileNamePreview(lpofn: POPENFILENAMEA): BOOL; stdcall;
// GetOpenFileNamePreviewA
function GetSaveFileNamePreview(lpofn: POPENFILENAMEA): BOOL; stdcall;
// GetSaveFileNamePreviewA

implementation

function MKFOURCC(ch0, ch1, ch2, ch3: Char): FOURCC;
begin
  Result := (DWORD(Ord(ch0))) or (DWORD(Ord(ch1)) shl 8) or
    (DWORD(Ord(ch2)) shl 16) or (DWORD(Ord(ch3)) shl 24);
end;

function mmioFOURCC(ch0, ch1, ch2, ch3: Char): FOURCC;
begin
  Result := MKFOURCC(ch0, ch1, ch2, ch3);
end;

function aviTWOCC(ch0, ch1: Char): TWOCC;
begin
  Result := (word(Ord(ch0))) or (word(Ord(ch1)) shl 8);
end;

{ -- Query macros ------------------------------------------------------------- }

function ICQueryAbout(HIC: HIC): BOOL;
begin
  Result := ICSendMessage(HIC, ICM_ABOUT, DWORD(-1), ICMF_ABOUT_QUERY)
    = ICERR_OK;
end;

function ICAbout(HIC: HIC; hwnd: hwnd): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_ABOUT, hwnd, 0);
end;

function ICQueryConfigure(HIC: HIC): BOOL;
begin
  Result := ICSendMessage(HIC, ICM_CONFIGURE, DWORD(-1), ICMF_CONFIGURE_QUERY)
    = ICERR_OK;
end;

function ICConfigure(HIC: HIC; hwnd: hwnd): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_CONFIGURE, hwnd, 0);
end;

{ -- Get/Set state macros ----------------------------------------------------- }

function ICGetState(HIC: HIC; pv: PVOID; cb: DWORD): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_GETSTATE, DWORD(pv), cb);
end;

function ICSetState(HIC: HIC; pv: PVOID; cb: DWORD): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_SETSTATE, DWORD(pv), cb);
end;

function ICGetStateSize(HIC: HIC): DWORD;
begin
  Result := ICGetState(HIC, nil, 0);
end;

{ -- Get value macros --------------------------------------------------------- }

function ICGetDefaultQuality(HIC: HIC): DWORD;
begin
  ICSendMessage(HIC, ICM_GETDEFAULTQUALITY, DWORD(@Result), sizeof(Result));
end;

function ICGetDefaultKeyFrameRate(HIC: HIC): DWORD;
begin
  ICSendMessage(HIC, ICM_GETDEFAULTKEYFRAMERATE, DWORD(@Result),
    sizeof(Result));
end;

{ -- Draw window macro -------------------------------------------------------- }

function ICDrawWindow(HIC: HIC; prc: PRECT): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_WINDOW, DWORD(prc), sizeof(prc^));
end;

{ -- ICCompressBegin() - start compression from a source fmt to a dest fmt ---- }

function ICCompressBegin(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_COMPRESS_BEGIN, DWORD(lpbiInput),
    DWORD(lpbiOutput));
end;

{ -- ICCompressQuery() - determines if compression from src to dst is supp ---- }

function ICCompressQuery(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_COMPRESS_QUERY, DWORD(lpbiInput),
    DWORD(lpbiOutput));
end;

{ -- ICCompressGetFormat() - get the output format (fmt of compressed) -------- }

// if lpbiOutput is nil return the size in bytes needed for format.

function ICCompressGetFormat(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_COMPRESS_GET_FORMAT, DWORD(lpbiInput),
    DWORD(lpbiOutput));
end;

function ICCompressGetFormatSize(HIC: HIC; lpbi: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICCompressGetFormat(HIC, lpbi, nil);
end;

{ -- ICCompressSize() - return the maximal size of a compressed frame --------- }

function ICCompressGetSize(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_COMPRESS_GET_SIZE, DWORD(lpbiInput),
    DWORD(lpbiOutput));
end;

function ICCompressEnd(HIC: HIC): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_COMPRESS_END, 0, 0);
end;

{ -- ICDecompressBegin() - start compression from src fmt to a dest fmt ------- }

function ICDecompressBegin(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DECOMPRESS_BEGIN, DWORD(lpbiInput),
    DWORD(lpbiOutput));
end;

{ -- ICDecompressQuery() - determines if compression is supported ------------- }

function ICDecompressQuery(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DECOMPRESS_QUERY, DWORD(lpbiInput),
    DWORD(lpbiOutput));
end;

{ -- ICDecompressGetFormat - get the output fmt (fmt of uncompressed data) ---- }

// if lpbiOutput is NULL return the size in bytes needed for format.

function ICDecompressGetFormat(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DECOMPRESS_GET_FORMAT, DWORD(lpbiInput),
    DWORD(lpbiOutput));
end;

function ICDecompressGetFormatSize(HIC: HIC; lpbi: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICDecompressGetFormat(HIC, lpbi, nil);
end;

{ -- ICDecompressGetPalette() - get the output palette ------------------------ }

function ICDecompressGetPalette(HIC: HIC;
  lpbiInput, lpbiOutput: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DECOMPRESS_GET_PALETTE, DWORD(lpbiInput),
    DWORD(lpbiOutput));
end;

function ICDecompressSetPalette(HIC: HIC;
  lpbiPalette: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DECOMPRESS_SET_PALETTE,
    DWORD(lpbiPalette), 0);
end;

function ICDecompressEnd(HIC: HIC): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DECOMPRESS_END, 0, 0);
end;

{ -- ICDecompressEx() - decompress a single frame ----------------------------- }

function ICDecompressEx(HIC: HIC; dwFlags: DWORD; lpbiSrc: PBITMAPINFOHEADER;
  lpSrc: PVOID; xSrc: int; ySrc: int; dxSrc: int; dySrc: int;
  lpbiDst: PBITMAPINFOHEADER; lpDst: PVOID; xDst: int; yDst: int; dxDst: int;
  dyDst: int): DWORD; stdcall;
var
  ic: TICDECOMPRESSEX;
begin
  ic.dwFlags := dwFlags;
  ic.lpbiSrc := lpbiSrc;
  ic.lpSrc := lpSrc;
  ic.xSrc := xSrc;
  ic.ySrc := ySrc;
  ic.dxSrc := dxSrc;
  ic.dySrc := dySrc;
  ic.lpbiDst := lpbiDst;
  ic.lpDst := lpDst;
  ic.xDst := xDst;
  ic.yDst := yDst;
  ic.dxDst := dxDst;
  ic.dyDst := dyDst;

  // note that ICM swaps round the length and pointer
  // length in lparam2, pointer in lparam1
  Result := ICSendMessage(HIC, ICM_DECOMPRESSEX, DWORD(@ic), sizeof(ic));
end;

{ -- ICDecompressExBegin() - start compression from a src fmt to a dest fmt --- }

function ICDecompressExBegin(HIC: HIC; dwFlags: DWORD;
  lpbiSrc: PBITMAPINFOHEADER; lpSrc: PVOID; xSrc: int; ySrc: int; dxSrc: int;
  dySrc: int; lpbiDst: PBITMAPINFOHEADER; lpDst: PVOID; xDst: int; yDst: int;
  dxDst: int; dyDst: int): DWORD; stdcall;
var
  ic: TICDECOMPRESSEX;
begin
  ic.dwFlags := dwFlags;
  ic.lpbiSrc := lpbiSrc;
  ic.lpSrc := lpSrc;
  ic.xSrc := xSrc;
  ic.ySrc := ySrc;
  ic.dxSrc := dxSrc;
  ic.dySrc := dySrc;
  ic.lpbiDst := lpbiDst;
  ic.lpDst := lpDst;
  ic.xDst := xDst;
  ic.yDst := yDst;
  ic.dxDst := dxDst;
  ic.dyDst := dyDst;

  // note that ICM swaps round the length and pointer
  // length in lparam2, pointer in lparam1
  Result := ICSendMessage(HIC, ICM_DECOMPRESSEX_BEGIN, DWORD(@ic), sizeof(ic));
end;

{ -- ICDecompressExQuery() ---------------------------------------------------- }

function ICDecompressExQuery(HIC: HIC; dwFlags: DWORD;
  lpbiSrc: PBITMAPINFOHEADER; lpSrc: PVOID; xSrc: int; ySrc: int; dxSrc: int;
  dySrc: int; lpbiDst: PBITMAPINFOHEADER; lpDst: PVOID; xDst: int; yDst: int;
  dxDst: int; dyDst: int): DWORD; stdcall;
var
  ic: TICDECOMPRESSEX;
begin
  ic.dwFlags := dwFlags;
  ic.lpbiSrc := lpbiSrc;
  ic.lpSrc := lpSrc;
  ic.xSrc := xSrc;
  ic.ySrc := ySrc;
  ic.dxSrc := dxSrc;
  ic.dySrc := dySrc;
  ic.lpbiDst := lpbiDst;
  ic.lpDst := lpDst;
  ic.xDst := xDst;
  ic.yDst := yDst;
  ic.dxDst := dxDst;
  ic.dyDst := dyDst;

  // note that ICM swaps round the length and pointer
  // length in lparam2, pointer in lparam1
  Result := ICSendMessage(HIC, ICM_DECOMPRESSEX_QUERY, DWORD(@ic), sizeof(ic));
end;

function ICDecompressExEnd(HIC: HIC): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DECOMPRESSEX_END, 0, 0)
end;

function ICDrawSuggestFormat(HIC: HIC; lpbiIn: PBITMAPINFOHEADER;
  lpbiOut: PBITMAPINFOHEADER; dxSrc: int; dySrc: int; dxDst: int; dyDst: int;
  hicDecomp: HIC): DWORD; stdcall;
var
  ic: TICDRAWSUGGEST;
begin
  ic.lpbiIn := lpbiIn;
  ic.lpbiSuggest := lpbiOut;
  ic.dxSrc := dxSrc;
  ic.dySrc := dySrc;
  ic.dxDst := dxDst;
  ic.dyDst := dyDst;
  ic.hicDecompressor := hicDecomp;

  // note that ICM swaps round the length and pointer
  // length in lparam2, pointer in lparam1
  Result := ICSendMessage(HIC, ICM_DRAW_SUGGESTFORMAT, DWORD(@ic), sizeof(ic));
end;

{ -- ICDrawQuery() - determines if the compressor is willing to render fmt ---- }

function ICDrawQuery(HIC: HIC; lpbiInput: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_QUERY, DWORD(lpbiInput), 0);
end;

function ICDrawChangePalette(HIC: HIC; lpbiInput: PBITMAPINFOHEADER): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_CHANGEPALETTE, DWORD(lpbiInput), 0);
end;

function ICGetBuffersWanted(HIC: HIC; lpdwBuffers: PDWORD): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_GETBUFFERSWANTED, DWORD(lpdwBuffers), 0);
end;

function ICDrawEnd(HIC: HIC): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_END, 0, 0);
end;

function ICDrawStart(HIC: HIC): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_START, 0, 0);
end;

function ICDrawStartPlay(HIC: HIC; lFrom, lTo: DWORD): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_START_PLAY, lFrom, lTo);
end;

function ICDrawStop(HIC: HIC): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_STOP, 0, 0);
end;

function ICDrawStopPlay(HIC: HIC): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_STOP_PLAY, 0, 0);
end;

function ICDrawGetTime(HIC: HIC; lplTime: PDWORD): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_GETTIME, DWORD(lplTime), 0);
end;

function ICDrawSetTime(HIC: HIC; lTime: DWORD): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_SETTIME, lTime, 0);
end;

function ICDrawRealize(HIC: HIC; hdc: hdc; fBackground: BOOL): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_REALIZE, DWORD(hdc),
    DWORD(fBackground));
end;

function ICDrawFlush(HIC: HIC): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_FLUSH, 0, 0);
end;

function ICDrawRenderBuffer(HIC: HIC): DWORD;
begin
  Result := ICSendMessage(HIC, ICM_DRAW_RENDERBUFFER, 0, 0);
end;

{ -- ICSetStatusProc() - Set the status callback function --------------------- }

// ICMessage is not supported on NT

function ICSetStatusProc(HIC: HIC; dwFlags: DWORD; LPARAM: DWORD;
  fpfnStatus: TICStatusProc): DWORD; stdcall;
var
  ic: TICSETSTATUSPROC;
begin
  ic.dwFlags := dwFlags;
  ic.LPARAM := LPARAM;
  ic.Status := fpfnStatus;

  // note that ICM swaps round the length and pointer
  // length in lparam2, pointer in lparam1
  Result := ICSendMessage(HIC, ICM_SET_STATUS_PROC, DWORD(@ic), sizeof(ic));
end;

{ == Helper routines for DrawDib and MCIAVI... ================================ }

function ICDecompressOpen(fccType, fccHandler: DWORD;
  lpbiIn, lpbiOut: PBITMAPINFOHEADER): HIC;
begin
  Result := ICLocate(fccType, fccHandler, lpbiIn, lpbiOut, ICMODE_DECOMPRESS);
end;

function ICDrawOpen(fccType, fccHandler: DWORD; lpbiIn: PBITMAPINFOHEADER): HIC;
begin
  Result := ICLocate(fccType, fccHandler, lpbiIn, nil, ICMODE_DRAW);
end;

{ -- DrawDibUpdate() - redraw last image (may only be valid with DDF_BUFFER) -- }

function DrawDibUpdate(hdd: HDRAWDIB; hdc: hdc; x, y: int): BOOL;
begin
  Result := DrawDibDraw(hdd, hdc, x, y, 0, 0, nil, nil, 0, 0, 0, 0, DDF_UPDATE);
end;

{ == Useful macros ============================================================ }

{ -- Macro to get stream number out of a FOURCC ckid -------------------------- }

function FromHex(n: BYTE): BYTE;
begin
  if n >= Ord('A') then
    Result := Ord(n) + 10 - Ord('A')
  else
    Result := Ord(n) - Ord('0');
end;

function StreamFromFOURCC(fcc: DWORD): BYTE;
begin
  Result := (FromHex(Lo(LoWord(fcc))) shl 4) + FromHex(Hi(LoWord(fcc)));
end;

{ -- Macro to get TWOCC chunk type out of a FOURCC ckid ----------------------- }

function TWOCCFromFOURCC(fcc: DWORD): word;
begin
  Result := HiWord(fcc);
end;

{ -- Macro to make a ckid for a chunk out of a TWOCC and a stream num (0-255) - }

function ToHex(n: BYTE): BYTE;
begin
  if n > 9 then
    Result := n - 10 + Ord('A')
  else
    Result := n + Ord('0');
end;

function MAKEAVICKID(tcc: word; stream: BYTE): DWORD;
begin
  Result := MakeLONG((ToHex(stream and $0F) shl 8) or
    ToHex((stream and $F0) shr 4), tcc);
end;

{ -- Helper macros ------------------------------------------------------------ }

function AVIStreamSampleToSample(pavi1, pavi2: IAVIStream; l: LONG): LONG;
begin
  Result := AVIStreamTimeToSample(pavi1, AVIStreamSampleToTime(pavi2, l));
end;

function AVIStreamNextSample(pavi: IAVIStream; l: LONG): LONG;
begin
  Result := AVIStreamFindSample(pavi, l + 1, FIND_NEXT or FIND_ANY);
end;

function AVIStreamPrevSample(pavi: IAVIStream; l: LONG): LONG;
begin
  Result := AVIStreamFindSample(pavi, l - 1, FIND_PREV or FIND_ANY);
end;

function AVIStreamNearestSample(pavi: IAVIStream; l: LONG): LONG;
begin
  Result := AVIStreamFindSample(pavi, l, FIND_PREV or FIND_ANY);
end;

function AVIStreamNextKeyFrame(pavi: IAVIStream; l: LONG): LONG;
begin
  Result := AVIStreamFindSample(pavi, l + 1, FIND_NEXT or FIND_KEY);
end;

function AVIStreamPrevKeyFrame(pavi: IAVIStream; l: LONG): LONG;
begin
  Result := AVIStreamFindSample(pavi, l - 1, FIND_PREV or FIND_KEY);
end;

function AVIStreamNearestKeyFrame(pavi: IAVIStream; l: LONG): LONG;
begin
  Result := AVIStreamFindSample(pavi, l, FIND_PREV or FIND_KEY)
end;

function AVIStreamIsKeyFrame(pavi: IAVIStream; l: LONG): BOOL;
begin
  Result := AVIStreamNearestKeyFrame(pavi, l) = l;
end;

function AVIStreamPrevSampleTime(pavi: IAVIStream; t: LONG): LONG;
begin
  Result := AVIStreamSampleToTime(pavi, AVIStreamPrevSample(pavi,
    AVIStreamTimeToSample(pavi, t)));
end;

function AVIStreamNextSampleTime(pavi: IAVIStream; t: LONG): LONG;
begin
  Result := AVIStreamSampleToTime(pavi, AVIStreamNextSample(pavi,
    AVIStreamTimeToSample(pavi, t)));
end;

function AVIStreamNearestSampleTime(pavi: IAVIStream; t: LONG): LONG;
begin
  Result := AVIStreamSampleToTime(pavi, AVIStreamNearestSample(pavi,
    AVIStreamTimeToSample(pavi, t)));
end;

function AVIStreamNextKeyFrameTime(pavi: IAVIStream; t: LONG): LONG;
begin
  Result := AVIStreamSampleToTime(pavi, AVIStreamNextKeyFrame(pavi,
    AVIStreamTimeToSample(pavi, t)));
end;

function AVIStreamPrevKeyFrameTime(pavi: IAVIStream; t: LONG): LONG;
begin
  Result := AVIStreamSampleToTime(pavi, AVIStreamPrevKeyFrame(pavi,
    AVIStreamTimeToSample(pavi, t)));
end;

function AVIStreamNearestKeyFrameTime(pavi: IAVIStream; t: LONG): LONG;
begin
  Result := AVIStreamSampleToTime(pavi, AVIStreamNearestKeyFrame(pavi,
    AVIStreamTimeToSample(pavi, t)));
end;

function AVIStreamStartTime(pavi: IAVIStream): LONG;
begin
  Result := AVIStreamSampleToTime(pavi, AVIStreamStart(pavi));
end;

function AVIStreamLengthTime(pavi: IAVIStream): LONG;
begin
  Result := AVIStreamSampleToTime(pavi, AVIStreamLength(pavi));
end;

function AVIStreamEnd(pavi: IAVIStream): LONG;
begin
  Result := AVIStreamStart(pavi) + AVIStreamLength(pavi);
end;

function AVIStreamEndTime(pavi: IAVIStream): LONG;
begin
  Result := AVIStreamSampleToTime(pavi, AVIStreamEnd(pavi));
end;

function AVIStreamSampleSize(pavi: IAVIStream; lPos: LONG; plSize: PLONG): LONG;
begin
  Result := AVIStreamRead(pavi, lPos, 1, nil, 0, plSize, nil);
end;

function AVIStreamFormatSize(pavi: IAVIStream; lPos: LONG;
  plSize: PLONG): HResult;
begin
  Result := AVIStreamReadFormat(pavi, lPos, nil, plSize);
end;

function AVIStreamDataSize(pavi: IAVIStream; fcc: DWORD; plSize: PLONG)
  : HResult;
begin
  Result := AVIStreamReadData(pavi, fcc, nil, plSize)
end;

{ == MCIWnd =================================================================== }

function MCIWndSM(hwnd: hwnd; msg: UINT; wParam: wParam; LPARAM: LPARAM): DWORD;
begin
  Result := SendMessage(hwnd, msg, wParam, LPARAM);
end;

{ -- Can macros --------------------------------------------------------------- }

function MCIWndCanPlay(hwnd: hwnd): BOOL;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_CAN_PLAY, 0, 0) <> 0;
end;

function MCIWndCanRecord(hwnd: hwnd): BOOL;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_CAN_RECORD, 0, 0) <> 0;
end;

function MCIWndCanSave(hwnd: hwnd): BOOL;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_CAN_SAVE, 0, 0) <> 0;
end;

function MCIWndCanWindow(hwnd: hwnd): BOOL;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_CAN_WINDOW, 0, 0) <> 0;
end;

function MCIWndCanEject(hwnd: hwnd): BOOL;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_CAN_EJECT, 0, 0) <> 0;
end;

function MCIWndCanConfig(hwnd: hwnd): BOOL;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_CAN_CONFIG, 0, 0) <> 0;
end;

function MCIWndPaletteKick(hwnd: hwnd): BOOL;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_PALETTEKICK, 0, 0) <> 0;
end;

function MCIWndSave(hwnd: hwnd; szFile: LPCSTR): DWORD;
begin
  Result := MCIWndSM(hwnd, MCI_SAVE, 0, LPARAM(szFile));
end;

function MCIWndSaveDialog(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSave(hwnd, LPCSTR(-1));
end;

// If you dont give a device it will use the current device....

function MCIWndNew(hwnd: hwnd; lp: PVOID): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_NEW, 0, LPARAM(lp));
end;

function MCIWndRecord(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCI_RECORD, 0, 0);
end;

function MCIWndOpen(hwnd: hwnd; sz: LPCSTR; f: BOOL): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_OPEN, wParam(f), LPARAM(sz));
end;

function MCIWndOpenDialog(hwnd: hwnd): DWORD;
begin
  Result := MCIWndOpen(hwnd, LPCSTR(-1), False);
end;

function MCIWndClose(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCI_CLOSE, 0, 0);
end;

function MCIWndPlay(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCI_PLAY, 0, 0);
end;

function MCIWndStop(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCI_STOP, 0, 0);
end;

function MCIWndPause(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCI_PAUSE, 0, 0);
end;

function MCIWndResume(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCI_RESUME, 0, 0);
end;

function MCIWndSeek(hwnd: hwnd; lPos: DWORD): DWORD;
begin
  Result := MCIWndSM(hwnd, MCI_SEEK, 0, lPos);
end;

function MCIWndEject(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_EJECT, 0, 0);
end;

function MCIWndHome(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSeek(hwnd, MCIWND_START);
end;

function MCIWndEnd(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSeek(hwnd, MCIWND_END);
end;

function MCIWndGetSource(hwnd: hwnd; prc: PRECT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GET_SOURCE, 0, LPARAM(prc));
end;

function MCIWndPutSource(hwnd: hwnd; prc: PRECT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_PUT_SOURCE, 0, LPARAM(prc));
end;

function MCIWndGetDest(hwnd: hwnd; prc: PRECT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GET_DEST, 0, LPARAM(prc));
end;

function MCIWndPutDest(hwnd: hwnd; prc: PRECT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_PUT_DEST, 0, LPARAM(prc));
end;

function MCIWndPlayReverse(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_PLAYREVERSE, 0, 0);
end;

function MCIWndPlayFrom(hwnd: hwnd; lPos: DWORD): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_PLAYFROM, 0, lPos);
end;

function MCIWndPlayTo(hwnd: hwnd; lPos: DWORD): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_PLAYTO, 0, lPos);
end;

function MCIWndPlayFromTo(hwnd: hwnd; lStart, lEnd: DWORD): DWORD;
begin
  MCIWndSeek(hwnd, lStart);
  Result := MCIWndPlayTo(hwnd, lEnd);
end;

function MCIWndGetDeviceID(hwnd: hwnd): UINT;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETDEVICEID, 0, 0);
end;

function MCIWndGetAlias(hwnd: hwnd): UINT;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETALIAS, 0, 0);
end;

function MCIWndGetMode(hwnd: hwnd; lp: LPCSTR; len: UINT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETMODE, len, LPARAM(lp));
end;

function MCIWndGetPosition(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETPOSITION, 0, 0);
end;

function MCIWndGetPositionString(hwnd: hwnd; lp: LPCSTR; len: UINT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETPOSITION, len, LPARAM(lp));
end;

function MCIWndGetStart(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETSTART, 0, 0);
end;

function MCIWndGetLength(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETLENGTH, 0, 0);
end;

function MCIWndGetEnd(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETEND, 0, 0);
end;

function MCIWndStep(hwnd: hwnd; n: DWORD): DWORD;
begin
  Result := MCIWndSM(hwnd, MCI_STEP, 0, n);
end;

procedure MCIWndDestroy(hwnd: hwnd);
begin
  MCIWndSM(hwnd, WM_CLOSE, 0, 0);
end;

procedure MCIWndSetZoom(hwnd: hwnd; iZoom: UINT);
begin
  MCIWndSM(hwnd, MCIWNDM_SETZOOM, 0, iZoom);
end;

function MCIWndGetZoom(hwnd: hwnd): UINT;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETZOOM, 0, 0);
end;

function MCIWndSetVolume(hwnd: hwnd; iVol: UINT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_SETVOLUME, 0, iVol);
end;

function MCIWndGetVolume(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETVOLUME, 0, 0);
end;

function MCIWndSetSpeed(hwnd: hwnd; iSpeed: UINT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_SETSPEED, 0, iSpeed);
end;

function MCIWndGetSpeed(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETSPEED, 0, 0);
end;

function MCIWndSetTimeFormat(hwnd: hwnd; lp: LPCSTR): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_SETTIMEFORMAT, 0, LPARAM(lp));
end;

function MCIWndGetTimeFormat(hwnd: hwnd; lp: LPCSTR; len: UINT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETTIMEFORMAT, len, LPARAM(lp));
end;

procedure MCIWndValidateMedia(hwnd: hwnd);
begin
  MCIWndSM(hwnd, MCIWNDM_VALIDATEMEDIA, 0, 0);
end;

procedure MCIWndSetRepeat(hwnd: hwnd; f: BOOL);
begin
  MCIWndSM(hwnd, MCIWNDM_SETREPEAT, 0, LPARAM(f));
end;

function MCIWndGetRepeat(hwnd: hwnd): BOOL;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETREPEAT, 0, 0) <> 0;
end;

function MCIWndUseFrames(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSetTimeFormat(hwnd, 'frames');
end;

function MCIWndUseTime(hwnd: hwnd): DWORD;
begin
  Result := MCIWndSetTimeFormat(hwnd, 'ms');
end;

procedure MCIWndSetActiveTimer(hwnd: hwnd; active: UINT);
begin
  MCIWndSM(hwnd, MCIWNDM_SETACTIVETIMER, active, 0);
end;

procedure MCIWndSetInactiveTimer(hwnd: hwnd; inactive: UINT);
begin
  MCIWndSM(hwnd, MCIWNDM_SETINACTIVETIMER, inactive, 0);
end;

procedure MCIWndSetTimers(hwnd: hwnd; active, inactive: UINT);
begin
  MCIWndSM(hwnd, MCIWNDM_SETTIMERS, active, inactive);
end;

function MCIWndGetActiveTimer(hwnd: hwnd): UINT;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETACTIVETIMER, 0, 0);
end;

function MCIWndGetInactiveTimer(hwnd: hwnd): UINT;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETINACTIVETIMER, 0, 0);
end;

function MCIWndRealize(hwnd: hwnd; fBkgnd: BOOL): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_REALIZE, wParam(fBkgnd), 0);
end;

function MCIWndSendString(hwnd: hwnd; sz: LPCSTR): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_SENDSTRING, 0, LPARAM(sz));
end;

function MCIWndReturnString(hwnd: hwnd; lp: LPSTR; len: UINT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_RETURNSTRING, len, LPARAM(lp));
end;

function MCIWndGetError(hwnd: hwnd; lp: LPSTR; len: UINT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETERROR, len, LPARAM(lp));
end;

function MCIWndGetPalette(hwnd: hwnd): HPALETTE;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETPALETTE, 0, 0);
end;

function MCIWndSetPalette(hwnd: hwnd; hpal: HPALETTE): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_SETPALETTE, hpal, 0);
end;

function MCIWndGetFileName(hwnd: hwnd; lp: LPCSTR; len: UINT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETFILENAME, len, LPARAM(lp));
end;

function MCIWndGetDevice(hwnd: hwnd; lp: LPCSTR; len: UINT): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETDEVICE, len, LPARAM(lp));
end;

function MCIWndGetStyles(hwnd: hwnd): UINT;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_GETSTYLES, 0, 0);
end;

function MCIWndChangeStyles(hwnd: hwnd; mask: UINT; value: DWORD): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_CHANGESTYLES, mask, value);
end;

function MCIWndOpenInterface(hwnd: hwnd; pUnk: PUnknown): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_OPENINTERFACE, 0, LPARAM(pUnk));
end;

function MCIWndSetOwner(hwnd: hwnd; hwndP: hwnd): DWORD;
begin
  Result := MCIWndSM(hwnd, MCIWNDM_SETOWNER, hwndP, 0);
end;

{ == AVICAP - Window class for AVI capture ==================================== }

function AVICapSM(hwnd: hwnd; m: UINT; w: wParam; l: LPARAM): DWORD;
begin
  if IsWindow(hwnd) then
    Result := SendMessage(hwnd, m, w, l)
  else
    Result := 0;
end;

{ -- Message crackers for above ----------------------------------------------- }

function capSetCallbackOnError(hwnd: hwnd; fpProc: TCAPERRORCALLBACK): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_CALLBACK_ERROR, 0, LPARAM(@fpProc)) <> 0;
end;

function capSetCallbackOnStatus(hwnd: hwnd; fpProc: TCAPSTATUSCALLBACK): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_CALLBACK_STATUS, 0, LPARAM(@fpProc)) <> 0;
end;

function capSetCallbackOnYield(hwnd: hwnd; fpProc: TCAPYIELDCALLBACK): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_CALLBACK_YIELD, 0, LPARAM(@fpProc)) <> 0;
end;

function capSetCallbackOnFrame(hwnd: hwnd; fpProc: TCAPVIDEOCALLBACK): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_CALLBACK_FRAME, 0, LPARAM(@fpProc)) <> 0;
end;

function capSetCallbackOnVideoStream(hwnd: hwnd;
  fpProc: TCAPVIDEOCALLBACK): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0,
    LPARAM(@fpProc)) <> 0;
end;

function capSetCallbackOnWaveStream(hwnd: hwnd; fpProc: TCAPWAVECALLBACK): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_CALLBACK_WAVESTREAM, 0,
    LPARAM(@fpProc)) <> 0;
end;

function capSetCallbackOnCapControl(hwnd: hwnd;
  fpProc: TCAPCONTROLCALLBACK): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_CALLBACK_CAPCONTROL, 0,
    LPARAM(@fpProc)) <> 0;
end;

function capSetUserData(hwnd: hwnd; lUser: DWORD): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_USER_DATA, 0, lUser) <> 0;
end;

function capGetUserData(hwnd: hwnd): DWORD;
begin
  Result := AVICapSM(hwnd, WM_CAP_GET_USER_DATA, 0, 0);
end;

function capDriverConnect(hwnd: hwnd; i: int): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_DRIVER_CONNECT, i, 0) <> 0;
end;

function capDriverDisconnect(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_DRIVER_DISCONNECT, 0, 0) <> 0;
end;

function capDriverGetName(hwnd: hwnd; szName: LPSTR; wSize: word): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_DRIVER_GET_NAME, wSize, LPARAM(szName)) <> 0;
end;

function capDriverGetVersion(hwnd: hwnd; szVer: LPSTR; wSize: word): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_DRIVER_GET_VERSION, wSize,
    LPARAM(szVer)) <> 0;
end;

function capDriverGetCaps(hwnd: hwnd; s: PCAPDRIVERCAPS; wSize: word): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_DRIVER_GET_CAPS, wSize, LPARAM(s)) <> 0;
end;

function capFileSetCaptureFile(hwnd: hwnd; szName: LPCSTR): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_FILE_SET_CAPTURE_FILE, 0,
    LPARAM(szName)) <> 0;
end;

function capFileGetCaptureFile(hwnd: hwnd; szName: LPSTR; wSize: word): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_FILE_GET_CAPTURE_FILE, wSize,
    LPARAM(szName)) <> 0;
end;

function capFileAlloc(hwnd: hwnd; dwSize: DWORD): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_FILE_ALLOCATE, 0, dwSize) <> 0;
end;

function capFileSaveAs(hwnd: hwnd; szName: LPCSTR): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_FILE_SAVEAS, 0, LPARAM(szName)) <> 0;
end;

function capFileSetInfoChunk(hwnd: hwnd; lpInfoChunk: PCAPINFOCHUNK): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_FILE_SET_INFOCHUNK, 0,
    LPARAM(lpInfoChunk)) <> 0;
end;

function capFileSaveDIB(hwnd: hwnd; szName: LPCSTR): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_FILE_SAVEDIB, 0, LPARAM(szName)) <> 0;
end;

function capEditCopy(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_EDIT_COPY, 0, 0) <> 0;
end;

function capSetAudioFormat(hwnd: hwnd; s: PWAVEFORMATEX; wSize: word): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_AUDIOFORMAT, wSize, LPARAM(s)) <> 0;
end;

function capGetAudioFormat(hwnd: hwnd; s: PWAVEFORMATEX; wSize: word): DWORD;
begin
  Result := AVICapSM(hwnd, WM_CAP_GET_AUDIOFORMAT, wSize, LPARAM(s));
end;

function capGetAudioFormatSize(hwnd: hwnd): DWORD;
begin
  Result := AVICapSM(hwnd, WM_CAP_GET_AUDIOFORMAT, 0, 0);
end;

function capDlgVideoFormat(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0) <> 0;
end;

function capDlgVideoSource(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0) <> 0;
end;

function capDlgVideoDisplay(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_DLG_VIDEODISPLAY, 0, 0) <> 0;
end;

function capDlgVideoCompression(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_DLG_VIDEOCOMPRESSION, 0, 0) <> 0;
end;

function capGetVideoFormat(hwnd: hwnd; s: PVOID; wSize: word): DWORD;
begin
  Result := AVICapSM(hwnd, WM_CAP_GET_VIDEOFORMAT, wSize, LPARAM(s));
end;

function capGetVideoFormatSize(hwnd: hwnd): DWORD;
begin
  Result := AVICapSM(hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0);
end;

function capSetVideoFormat(hwnd: hwnd; s: PVOID; wSize: word): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_VIDEOFORMAT, wSize, LPARAM(s)) <> 0;
end;

function capPreview(hwnd: hwnd; f: BOOL): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_PREVIEW, wParam(f), 0) <> 0;
end;

function capPreviewRate(hwnd: hwnd; wMS: word): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_PREVIEWRATE, wMS, 0) <> 0;
end;

function capOverlay(hwnd: hwnd; f: BOOL): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_OVERLAY, wParam(f), 0) <> 0;
end;

function capPreviewScale(hwnd: hwnd; f: BOOL): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_SCALE, wParam(f), 0) <> 0;
end;

function capGetStatus(hwnd: hwnd; s: PCAPSTATUS; wSize: word): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_GET_STATUS, wSize, LPARAM(s)) <> 0;
end;

function capSetScrollPos(hwnd: hwnd; lpP: PPOINT): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_SCROLL, 0, LPARAM(lpP)) <> 0;
end;

function capGrabFrame(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_GRAB_FRAME, 0, 0) <> 0;
end;

function capGrabFrameNoStop(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0) <> 0;
end;

function capCaptureSequence(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SEQUENCE, 0, 0) <> 0;
end;

function capCaptureSequenceNoFile(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SEQUENCE_NOFILE, 0, 0) <> 0;
end;

function capCaptureStop(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_STOP, 0, 0) <> 0;
end;

function capCaptureAbort(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_ABORT, 0, 0) <> 0;
end;

function capCaptureSingleFrameOpen(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SINGLE_FRAME_OPEN, 0, 0) <> 0;
end;

function capCaptureSingleFrameClose(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SINGLE_FRAME_CLOSE, 0, 0) <> 0;
end;

function capCaptureSingleFrame(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SINGLE_FRAME, 0, 0) <> 0;
end;

function capCaptureGetSetup(hwnd: hwnd; s: PCAPTUREPARMS; wSize: word): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_GET_SEQUENCE_SETUP, wSize, LPARAM(s)) <> 0;
end;

function capCaptureSetSetup(hwnd: hwnd; s: PCAPTUREPARMS; wSize: word): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_SEQUENCE_SETUP, wSize, LPARAM(s)) <> 0;
end;

function capSetMCIDeviceName(hwnd: hwnd; szName: LPCSTR): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_SET_MCI_DEVICE, 0, LPARAM(szName)) <> 0;
end;

function capGetMCIDeviceName(hwnd: hwnd; szName: LPSTR; wSize: word): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_GET_MCI_DEVICE, wSize, LPARAM(szName)) <> 0;
end;

function capPaletteOpen(hwnd: hwnd; szName: LPCSTR): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_PAL_OPEN, 0, LPARAM(szName)) <> 0;
end;

function capPaletteSave(hwnd: hwnd; szName: LPCSTR): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_PAL_SAVE, 0, LPARAM(szName)) <> 0;
end;

function capPalettePaste(hwnd: hwnd): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_PAL_PASTE, 0, 0) <> 0;
end;

function capPaletteAuto(hwnd: hwnd; iFrames, iColors: int): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_PAL_AUTOCREATE, iFrames, iColors) <> 0;
end;

function capPaletteManual(hwnd: hwnd; fGrab: BOOL; iColors: int): BOOL;
begin
  Result := AVICapSM(hwnd, WM_CAP_PAL_MANUALCREATE, wParam(fGrab),
    iColors) <> 0;
end;

{ == Externals ================================================================ }

const
  VFWDLL = 'MSVFW32.DLL';
  AVIFILDLL = 'AVIFIL32.DLL';
  AVICAPDLL = 'AVICAP32.DLL';

  { -- Returns version of VFW --------------------------------------------------- }

function VideoForWindowsVersion: DWORD; pascal; external VFWDLL;

{ -- Call these to start stop using VfW from your app ------------------------- }

{ TODO: Where are these functions? }
{
  function    InitVFW: LONG; stdcall;
  function    TermVFW: LONG; stdcall; }

{ -- ICM function declarations ------------------------------------------------ }

function ICInfo(fccType, fccHandler: DWORD; lpicinfo: PICINFO): BOOL; stdcall;
  external VFWDLL;
function ICInstall(fccType, fccHandler: DWORD; LPARAM: LPARAM; szDesc: LPSTR;
  wFlags: UINT): BOOL; stdcall; external VFWDLL;
function ICRemove(fccType, fccHandler: DWORD; wFlags: UINT): BOOL; stdcall;
  external VFWDLL;
function ICGetInfo(HIC: HIC; PICINFO: PICINFO; cb: DWORD): DWORD; stdcall;
  external VFWDLL;

function ICOpen(fccType, fccHandler: DWORD; wMode: UINT): HIC; stdcall;
  external VFWDLL;
function ICOpenFunction(fccType, fccHandler: DWORD; wMode: UINT;
  lpfnHandler: TFarProc): HIC; stdcall; external VFWDLL;
function ICClose(HIC: HIC): DWORD; stdcall; external VFWDLL;

function ICSendMessage(HIC: HIC; msg: UINT; dw1, dw2: DWORD): DWORD; stdcall;
  external VFWDLL;

{ == Compression functions ==================================================== }

{ -- ICCompress() - compress a single frame ----------------------------------- }

function ICCompress(HIC: HIC; dwFlags: DWORD; // flags
  lpbiOutput: PBITMAPINFOHEADER; // output format
  lpData: PVOID; // output data
  lpbiInput: PBITMAPINFOHEADER; // format of frame to compress
  lpBits: PVOID; // frame data to compress
  lpckid: PDWORD; // ckid for data in AVI file
  lpdwFlags: PDWORD; // flags in the AVI index.
  lFrameNum: DWORD; // frame number of seq.
  dwFrameSize: DWORD; // reqested size in bytes. (if non zero)
  dwQuality: DWORD; // quality within one frame
  lpbiPrev: PBITMAPINFOHEADER; // format of previous frame
  lpPrev: PVOID // previous frame
  ): DWORD; cdecl; external VFWDLL;

{ == Decompression functions ================================================== }

{ -- ICDecompress() - decompress a single frame ------------------------------- }

function ICDecompress(HIC: HIC; dwFlags: DWORD; // flags (from AVI index...)
  lpbiFormat: PBITMAPINFOHEADER; // BITMAPINFO of compressed data
  // biSizeImage has the chunk size
  lpData: PVOID; // data
  lpbi: PBITMAPINFOHEADER; // DIB to decompress to
  lpBits: PVOID): DWORD; cdecl; external VFWDLL;

{ == Drawing functions ======================================================== }

{ -- ICDrawBegin() - start decompressing data with fmt directly to screen ----- }

// return zero if the decompressor supports drawing.

function ICDrawBegin(HIC: HIC; dwFlags: DWORD; // flags
  hpal: HPALETTE; // palette to draw with
  hwnd: hwnd; // window to draw to
  hdc: hdc; // HDC to draw to
  xDst: int; // destination rectangle
  yDst: int; dxDst: int; dyDst: int; lpbi: PBITMAPINFOHEADER;
  // format of frame to draw
  xSrc: int; // source rectangle
  ySrc: int; dxSrc: int; dySrc: int; dwRate: DWORD;
  // frames/second = (dwRate/dwScale)
  dwScale: DWORD): DWORD; cdecl; external VFWDLL;

{ -- ICDraw() - decompress data directly to the screen ------------------------ }

function ICDraw(HIC: HIC; dwFlags: DWORD; // flags
  lpFormat: PVOID; // format of frame to decompress
  lpData: PVOID; // frame data to decompress
  cbData: DWORD; // size of data
  lTime: DWORD // time to draw this frame
  ): DWORD; cdecl; external VFWDLL;

{ == Helper routines for DrawDib and MCIAVI... ================================ }

function ICLocate(fccType, fccHandler: DWORD;
  lpbiIn, lpbiOut: PBITMAPINFOHEADER; wFlags: word): HIC; stdcall;
  external VFWDLL;
function ICGetDisplayFormat(HIC: HIC; lpbiIn, lpbiOut: PBITMAPINFOHEADER;
  BitDepth: int; dx, dy: int): HIC; stdcall; external VFWDLL;

{ == Higher level functions =================================================== }

function ICImageCompress(HIC: HIC; // compressor to use
  uiFlags: UINT; // flags (none yet)
  lpbiIn: PBITMAPINFO; // format to compress from
  lpBits: PVOID; // data to compress
  lpbiOut: PBITMAPINFO; // compress to this (NULL ==> default)
  lQuality: LONG; // quality to use
  plSize: PDWORD // compress to this size (0=whatever)
  ): THandle; stdcall; external VFWDLL;

function ICImageDecompress(HIC: HIC; // compressor to use
  uiFlags: UINT; // flags (none yet)
  lpbiIn: PBITMAPINFO; // format to decompress from
  lpBits: PVOID; // data to decompress
  lpbiOut: PBITMAPINFO // decompress to this (NULL ==> default)
  ): THandle; stdcall; external VFWDLL;

{ -- ICCompressorChoose() - allows user to choose compressor, quality etc... -- }

function ICCompressorChoose(hwnd: hwnd; // parent window for dialog
  uiFlags: UINT; // flags
  pvIn: PVOID; // input format (optional)
  lpData: PVOID; // input data (optional)
  pc: PCOMPVARS; // data about the compressor/dlg
  lpszTitle: LPSTR // dialog title (optional)
  ): BOOL; stdcall; external VFWDLL;

function ICSeqCompressFrameStart(pc: PCOMPVARS; lpbiIn: PBITMAPINFO): BOOL;
  stdcall; external VFWDLL;
procedure ICSeqCompressFrameEnd(pc: PCOMPVARS); stdcall; external VFWDLL;

function ICSeqCompressFrame(pc: PCOMPVARS; // set by ICCompressorChoose
  uiFlags: UINT; // flags
  lpBits: PVOID; // input DIB bits
  pfKey: PBOOL; // did it end up being a key frame?
  plSize: PDWORD // size to compress to/of returned image
  ): PVOID; stdcall; external VFWDLL;

procedure ICCompressorFree(pc: PCOMPVARS); stdcall; external VFWDLL;

{ == DrawDib functions ======================================================== }

{ -- DrawDibOpen() ------------------------------------------------------------ }

function DrawDibOpen: HDRAWDIB; stdcall; external VFWDLL;

{ -- DrawDibClose() ----------------------------------------------------------- }

function DrawDibClose(hdd: HDRAWDIB): BOOL; stdcall; external VFWDLL;

{ -- DrawDibGetBuffer() ------------------------------------------------------- }

function DrawDibGetBuffer(hdd: HDRAWDIB; lpbi: PBITMAPINFOHEADER; dwSize: DWORD;
  dwFlags: DWORD): PVOID; stdcall; external VFWDLL;

{ -- DrawDibGetPalette() - get the palette used for drawing DIBs -------------- }

function DrawDibGetPalette(hdd: HDRAWDIB): HPALETTE; stdcall; external VFWDLL;

{ -- DrawDibSetPalette() - set the palette used for drawing DIBs -------------- }

function DrawDibSetPalette(hdd: HDRAWDIB; hpal: HPALETTE): BOOL; stdcall;
  external VFWDLL;

{ -- DrawDibChangePalette() --------------------------------------------------- }

function DrawDibChangePalette(hdd: HDRAWDIB; iStart, iLen: int;
  lppe: PPALETTEENTRY): BOOL; stdcall; external VFWDLL;

{ -- DrawDibRealize() - realize the palette in a HDD -------------------------- }

function DrawDibRealize(hdd: HDRAWDIB; hdc: hdc; fBackground: BOOL): UINT;
  stdcall; external VFWDLL;

{ -- DrawDibStart() - start of streaming playback ----------------------------- }

function DrawDibStart(hdd: HDRAWDIB; rate: DWORD): BOOL; stdcall;
  external VFWDLL;

{ -- DrawDibStop() - start of streaming playback ------------------------------ }

function DrawDibStop(hdd: HDRAWDIB): BOOL; stdcall; external VFWDLL;

{ -- DrawDibBegin() - prepare to draw ----------------------------------------- }

function DrawDibBegin(hdd: HDRAWDIB; hdc: hdc; dxDst: int; dyDst: int;
  lpbi: PBITMAPINFOHEADER; dxSrc: int; dySrc: int; wFlags: UINT): BOOL; stdcall;
  external VFWDLL;

{ -- DrawDibDraw() - actually draw a DIB to the screen ------------------------ }

function DrawDibDraw(hdd: HDRAWDIB; hdc: hdc; xDst: int; yDst: int; dxDst: int;
  dyDst: int; lpbi: PBITMAPINFOHEADER; lpBits: PVOID; xSrc: int; ySrc: int;
  dxSrc: int; dySrc: int; wFlags: UINT): BOOL; stdcall; external VFWDLL;

{ -- DrawDibEnd() ------------------------------------------------------------- }

function DrawDibEnd(hdd: HDRAWDIB): BOOL; stdcall; external VFWDLL;

{ -- DrawDibTime() - for debugging purposes only ------------------------------ }

function DrawDibTime(hdd: HDRAWDIB; lpddtime: PDRAWDIBTIME): BOOL; stdcall;
  external VFWDLL;

{ -- Display profiling -------------------------------------------------------- }

function DrawDibProfileDisplay(lpbi: PBITMAPINFOHEADER): DWORD; stdcall;
  external VFWDLL;

{ -- Functions ---------------------------------------------------------------- }

procedure AVIFileInit; stdcall; external AVIFILDLL; // Call this first!
procedure AVIFileExit; stdcall; external AVIFILDLL;

function AVIFileAddRef(pfile: IAVIFile): ULONG; stdcall; external AVIFILDLL;
function AVIFileRelease(pfile: IAVIFile): ULONG; stdcall; external AVIFILDLL;

function AVIFileOpenA(var ppfile: IAVIFile; szFile: LPCSTR; uMode: UINT;
  lpHandler: PCLSID): HResult; stdcall; external AVIFILDLL;
function AVIFileOpenW(var ppfile: IAVIFile; szFile: LPCWSTR; uMode: UINT;
  lpHandler: PCLSID): HResult; stdcall; external AVIFILDLL;

{$IFDEF UNICODE}
function AVIFileOpen(var ppfile: IAVIFile; szFile: LPCWSTR; uMode: UINT;
  lpHandler: PCLSID): HResult; stdcall; external AVIFILDLL name 'AVIFileOpenW';
{$ELSE}
function AVIFileOpen(var ppfile: IAVIFile; szFile: LPCSTR; uMode: UINT;
  lpHandler: PCLSID): HResult; stdcall; external AVIFILDLL name 'AVIFileOpenA';
{$ENDIF}
function AVIFileInfoW(pfile: IAVIFile; var pfi: TAVIFileInfoW; lSize: LONG)
  : HResult; stdcall; external AVIFILDLL;
function AVIFileInfoA(pfile: IAVIFile; var pfi: TAVIFileInfoA; lSize: LONG)
  : HResult; stdcall; external AVIFILDLL;

{$IFDEF UNICODE}
function AVIFileInfo(pfile: IAVIFile; var pfi: TAVIFileInfo; lSize: LONG)
  : HResult; stdcall; external AVIFILDLL name 'AVIFileInfoW';
{$ELSE}
function AVIFileInfo(pfile: IAVIFile; var pfi: TAVIFileInfo; lSize: LONG)
  : HResult; stdcall; external AVIFILDLL name 'AVIFileInfoA';
{$ENDIF}
function AVIFileGetStream(pfile: IAVIFile; var ppavi: IAVIStream;
  fccType: DWORD; LPARAM: LONG): HResult; stdcall; external AVIFILDLL;

function AVIFileCreateStreamW(pfile: IAVIFile; var ppavi: IAVIStream;
  var psi: TAVIStreamInfoW): HResult; stdcall; external AVIFILDLL;
function AVIFileCreateStreamA(pfile: IAVIFile; var ppavi: IAVIStream;
  var psi: TAVIStreamInfoA): HResult; stdcall; external AVIFILDLL;

{$IFDEF UNICODE}
function AVIFileCreateStream(pfile: IAVIFile; var ppavi: IAVIStream;
  var psi: TAVIStreamInfo): HResult; stdcall;
  external AVIFILDLL name 'AVIFileCreateStreamW';
{$ELSE}
function AVIFileCreateStream(pfile: IAVIFile; var ppavi: IAVIStream;
  var psi: TAVIStreamInfo): HResult; stdcall;
  external AVIFILDLL name 'AVIFileCreateStreamA';
{$ENDIF}
function AVIFileWriteData(pfile: IAVIFile; ckid: DWORD; lpData: PVOID;
  cbData: LONG): HResult; stdcall; external AVIFILDLL;
function AVIFileReadData(pfile: IAVIFile; ckid: DWORD; lpData: PVOID;
  var lpcbData: LONG): HResult; stdcall; external AVIFILDLL;
function AVIFileEndRecord(pfile: IAVIFile): HResult; stdcall;
  external AVIFILDLL;

function AVIStreamAddRef(pavi: IAVIStream): ULONG; stdcall; external AVIFILDLL;
function AVIStreamRelease(pavi: IAVIStream): ULONG; stdcall; external AVIFILDLL;

function AVIStreamInfoW(pavi: IAVIStream; var psi: TAVIStreamInfoW; lSize: LONG)
  : HResult; stdcall; external AVIFILDLL;
function AVIStreamInfoA(pavi: IAVIStream; var psi: TAVIStreamInfoA; lSize: LONG)
  : HResult; stdcall; external AVIFILDLL;

{$IFDEF UNICODE}
function AVIStreamInfo(pavi: IAVIStream; var psi: TAVIStreamInfo; lSize: LONG)
  : HResult; stdcall; external AVIFILDLL name 'AVIStreamInfoW';
{$ELSE}
function AVIStreamInfo(pavi: IAVIStream; var psi: TAVIStreamInfo; lSize: LONG)
  : HResult; stdcall; external AVIFILDLL name 'AVIStreamInfoA';
{$ENDIF}
function AVIStreamFindSample(pavi: IAVIStream; lPos: LONG; lFlags: LONG): LONG;
  stdcall; external AVIFILDLL;
function AVIStreamReadFormat(pavi: IAVIStream; lPos: LONG; lpFormat: PVOID;
  lpcbFormat: PLONG): HResult; stdcall; external AVIFILDLL;
function AVIStreamSetFormat(pavi: IAVIStream; lPos: LONG; lpFormat: PVOID;
  cbFormat: LONG): HResult; stdcall; external AVIFILDLL;
function AVIStreamReadData(pavi: IAVIStream; fcc: DWORD; lp: PVOID; lpcb: PLONG)
  : HResult; stdcall; external AVIFILDLL;
function AVIStreamWriteData(pavi: IAVIStream; fcc: DWORD; lp: PVOID; cb: LONG)
  : HResult; stdcall; external AVIFILDLL;

function AVIStreamRead(pavi: IAVIStream; lStart: LONG; lSamples: LONG;
  lpBuffer: PVOID; cbBuffer: LONG; plBytes: PLONG; plSamples: PLONG): HResult;
  stdcall; external AVIFILDLL;

function AVIStreamWrite(pavi: IAVIStream; lStart: LONG; lSamples: LONG;
  lpBuffer: PVOID; cbBuffer: LONG; dwFlags: DWORD; plSampWritten: PLONG;
  plBytesWritten: PLONG): HResult; stdcall; external AVIFILDLL;

// Right now, these just use AVIStreamInfo() to get information, then
// return some of it.  Can they be more efficient?

function AVIStreamStart(pavi: IAVIStream): LONG; stdcall; external AVIFILDLL;
function AVIStreamLength(pavi: IAVIStream): LONG; stdcall; external AVIFILDLL;
function AVIStreamTimeToSample(pavi: IAVIStream; lTime: LONG): LONG; stdcall;
  external AVIFILDLL;
function AVIStreamSampleToTime(pavi: IAVIStream; lSample: LONG): LONG; stdcall;
  external AVIFILDLL;

function AVIStreamBeginStreaming(pavi: IAVIStream; lStart, lEnd: LONG;
  lRate: LONG): HResult; stdcall; external AVIFILDLL;
function AVIStreamEndStreaming(pavi: IAVIStream): HResult; stdcall;
  external AVIFILDLL;

{ -- Helper functions for using IGetFrame ------------------------------------- }

function AVIStreamGetFrameOpen_(pavi: IAVIStream; lpbiWanted: PBITMAPINFOHEADER)
  : pointer; stdcall; external AVIFILDLL name 'AVIStreamGetFrameOpen';
function AVIStreamGetFrame(pg: IGetFrame; lPos: LONG): PBITMAPINFOHEADER;
  stdcall; external AVIFILDLL;
function AVIStreamGetFrameClose(pg: IGetFrame): HResult; stdcall;
  external AVIFILDLL;

function AVIStreamGetFrameOpen(pavi: IAVIStream; lpbiWanted: PBITMAPINFOHEADER)
  : IGetFrame; stdcall;
begin
  pointer(Result) := AVIStreamGetFrameOpen_(pavi, lpbiWanted);
end;

// !!! We need some way to place an advise on a stream....
// STDAPI AVIStreamHasChanged   (PAVISTREAM pavi);

{ -- Shortcut function -------------------------------------------------------- }

function AVIStreamOpenFromFileA(var ppavi: IAVIStream; szFile: LPCSTR;
  fccType: DWORD; LPARAM: LONG; mode: UINT; pclsidHandler: PCLSID): HResult;
  stdcall; external AVIFILDLL;
function AVIStreamOpenFromFileW(var ppavi: IAVIStream; szFile: LPCWSTR;
  fccType: DWORD; LPARAM: LONG; mode: UINT; pclsidHandler: PCLSID): HResult;
  stdcall; external AVIFILDLL;

{$IFDEF UNICODE}
function AVIStreamOpenFromFile(var ppavi: IAVIStream; szFile: LPCWSTR;
  fccType: DWORD; LPARAM: LONG; mode: UINT; pclsidHandler: PCLSID): HResult;
  stdcall; external AVIFILDLL name 'AVIStreamOpenFromFileW';
{$ELSE}
function AVIStreamOpenFromFile(var ppavi: IAVIStream; szFile: LPCSTR;
  fccType: DWORD; LPARAM: LONG; mode: UINT; pclsidHandler: PCLSID): HResult;
  stdcall; external AVIFILDLL name 'AVIStreamOpenFromFileA';
{$ENDIF}
{ -- Use to create disembodied streams ---------------------------------------- }

function AVIStreamCreate(var ppavi: IAVIStream; lParam1, lParam2: LONG;
  pclsidHandler: PCLSID): HResult; stdcall; external AVIFILDLL;

// PHANDLER    AVIAPI AVIGetHandler         (PAVISTREAM pavi, PAVISTREAMHANDLER psh);
// PAVISTREAM  AVIAPI AVIGetStream          (PHANDLER p);

{ -- Stuff to support backward compat. ---------------------------------------- }

function AVIStreamFindKeyFrame(var pavi: IAVIStream; lPos: LONG; lFlags: LONG)
  : DWORD; stdcall; external AVIFILDLL name 'AVIStreamFindSample';

// Non-portable: this is alias for method name
// FindKeyFrame FindSample

function AVIStreamClose(pavi: IAVIStream): ULONG; stdcall;
  external AVIFILDLL name 'AVIStreamRelease';
function AVIFileClose(pfile: IAVIFile): ULONG; stdcall;
  external AVIFILDLL name 'AVIFileRelease';
procedure AVIStreamInit; stdcall; external AVIFILDLL name 'AVIFileInit';
procedure AVIStreamExit; stdcall; external AVIFILDLL name 'AVIFileExit';

{ == AVISave routines and structures ========================================== }

function AVIMakeCompressedStream(var ppsCompressed: IAVIStream;
  ppsSource: IAVIStream; lpOptions: PAVICOMPRESSOPTIONS; pclsidHandler: PCLSID)
  : HResult; stdcall; external AVIFILDLL;

// Non-portable: uses variable number of params
// EXTERN_C HRESULT CDECL AVISaveA (LPCSTR               szFile,
// CLSID FAR *pclsidHandler,
// AVISAVECALLBACK     lpfnCallback,
// int                 nStreams,
// PAVISTREAM      pfile,
// LPAVICOMPRESSOPTIONS lpOptions,
// ...);

function AVISaveVA(szFile: LPCSTR; pclsidHandler: PCLSID;
  lpfnCallback: TAVISAVECALLBACK; nStreams: int; var ppavi: IAVIStream;
  var plpOptions: PAVICOMPRESSOPTIONS): HResult; stdcall; external AVIFILDLL;

// Non-portable: uses variable number of params
// EXTERN_C HRESULT CDECL AVISaveW (LPCWSTR               szFile,
// CLSID FAR *pclsidHandler,
// AVISAVECALLBACK     lpfnCallback,
// int                 nStreams,
// PAVISTREAM      pfile,
// LPAVICOMPRESSOPTIONS lpOptions,
// ...);

function AVISaveVW(szFile: LPCWSTR; pclsidHandler: PCLSID;
  lpfnCallback: TAVISAVECALLBACK; nStreams: int; var ppavi: IAVIStream;
  var plpOptions: PAVICOMPRESSOPTIONS): HResult; stdcall; external AVIFILDLL;

// #define AVISave      AVISaveA

function AVISaveV(szFile: LPCSTR; pclsidHandler: PCLSID;
  lpfnCallback: TAVISAVECALLBACK; nStreams: int; var ppavi: IAVIStream;
  var plpOptions: PAVICOMPRESSOPTIONS): HResult; stdcall;
  external AVIFILDLL name 'AVISaveVA';

function AVISaveOptions(hwnd: hwnd; uiFlags: UINT; nStreams: int;
  var ppavi: IAVIStream; var plpOptions: PAVICOMPRESSOPTIONS): BOOL; stdcall;
  external AVIFILDLL;

function AVISaveOptionsFree(nStreams: int; var plpOptions: PAVICOMPRESSOPTIONS)
  : HResult; stdcall; external AVIFILDLL;

{ ----------------------------------------------------------------------------- }

function AVIBuildFilterW(lpszFilter: LPWSTR; cbFilter: LONG; fSaving: BOOL)
  : HResult; stdcall; external AVIFILDLL;
function AVIBuildFilterA(lpszFilter: LPSTR; cbFilter: LONG; fSaving: BOOL)
  : HResult; stdcall; external AVIFILDLL;

function AVIBuildFilter(lpszFilter: LPSTR; cbFilter: LONG; fSaving: BOOL)
  : HResult; stdcall; external AVIFILDLL name 'AVIBuildFilterA';

function AVIMakeFileFromStreams(var ppfile: IAVIFile; nStreams: int;
  var papStreams: IAVIStream): HResult; stdcall; external AVIFILDLL;

function AVIMakeStreamFromClipboard(cfFormat: UINT; hGlobal: THandle;
  var ppStream: IAVIStream): HResult; stdcall; external AVIFILDLL;

{ -- Clipboard routines ------------------------------------------------------- }

function AVIPutFileOnClipboard(pf: IAVIFile): HResult; stdcall;
  external AVIFILDLL;
function AVIGetFromClipboard(var lppf: IAVIFile): HResult; stdcall;
  external AVIFILDLL;
function AVIClearClipboard: HResult; stdcall; external AVIFILDLL;

{ -- Editing routines --------------------------------------------------------- }

function CreateEditableStream(var ppsEditable: IAVIStream; psSource: IAVIStream)
  : HResult; stdcall; external AVIFILDLL;

function EditStreamCut(pavi: IAVIStream; var plStart, plLength: LONG;
  var ppResult: IAVIStream): HResult; stdcall; external AVIFILDLL;
function EditStreamCopy(pavi: IAVIStream; var plStart, plLength: LONG;
  var ppResult: IAVIStream): HResult; stdcall; external AVIFILDLL;
function EditStreamPaste(pavi: IAVIStream; var plPos, plLength: LONG;
  pstream: IAVIStream; lStart, lEnd: LONG): HResult; stdcall;
  external AVIFILDLL;
function EditStreamClone(pavi: IAVIStream; var ppResult: IAVIStream): HResult;
  stdcall; external AVIFILDLL;

function EditStreamSetNameA(pavi: IAVIStream; lpszName: LPCSTR): HResult;
  stdcall; external AVIFILDLL;
function EditStreamSetNameW(pavi: IAVIStream; lpszName: LPCWSTR): HResult;
  stdcall; external AVIFILDLL;
function EditStreamSetInfoW(pavi: IAVIStream; lpInfo: PAVIStreamInfoW;
  cbInfo: LONG): HResult; stdcall; external AVIFILDLL;
function EditStreamSetInfoA(pavi: IAVIStream; lpInfo: PAVIStreamInfoA;
  cbInfo: LONG): HResult; stdcall; external AVIFILDLL;

function EditStreamSetInfo(pavi: IAVIStream; lpInfo: PAVIStreamInfoA;
  cbInfo: LONG): HResult; stdcall; external AVIFILDLL name 'EditStreamSetInfoA';
function EditStreamSetName(pavi: IAVIStream; lpszName: LPCSTR): HResult;
  stdcall; external AVIFILDLL name 'EditStreamSetNameA';

{ -- MCIWnd ------------------------------------------------------------------- }

function MCIWndCreateA(hwndParent: hwnd; hInstance: HINST; dwStyle: DWORD;
  szFile: LPCSTR): hwnd; cdecl; external VFWDLL;
function MCIWndCreateW(hwndParent: hwnd; hInstance: HINST; dwStyle: DWORD;
  szFile: LPCWSTR): hwnd; cdecl; external VFWDLL;

function MCIWndCreate(hwndParent: hwnd; hInstance: HINST; dwStyle: DWORD;
  szFile: LPCSTR): hwnd; cdecl; external VFWDLL name 'MCIWndCreateA';

function MCIWndRegisterClass: BOOL; cdecl; external VFWDLL;

{ == AVICAP - Window class for AVI capture ==================================== }

{ -- The only exported functions from AVICAP.DLL ------------------------------ }

function capCreateCaptureWindowA(lpszWindowName: LPCSTR; dwStyle: DWORD;
  x, y: int; nWidth, nHeight: int; hwndParent: hwnd; nID: int): hwnd; stdcall;
  external AVICAPDLL;

function capGetDriverDescriptionA(wDriverIndex: UINT; lpszName: LPSTR;
  cbName: int; lpszVer: LPSTR; cbVer: int): BOOL; stdcall; external AVICAPDLL;

function capCreateCaptureWindowW(lpszWindowName: LPCWSTR; dwStyle: DWORD;
  x, y: int; nWidth, nHeight: int; hwndParent: hwnd; nID: int): hwnd; stdcall;
  external AVICAPDLL;

function capGetDriverDescriptionW(wDriverIndex: UINT; lpszName: LPWSTR;
  cbName: int; lpszVer: LPWSTR; cbVer: int): BOOL; stdcall; external AVICAPDLL;

function capCreateCaptureWindow(lpszWindowName: LPCSTR; dwStyle: DWORD;
  x, y: int; nWidth, nHeight: int; hwndParent: hwnd; nID: int): hwnd; stdcall;
  external AVICAPDLL name 'capCreateCaptureWindowA';

function capGetDriverDescription(wDriverIndex: UINT; lpszName: LPSTR;
  cbName: int; lpszVer: LPSTR; cbVer: int): BOOL; stdcall;
  external AVICAPDLL name 'capGetDriverDescriptionA';

{ == FilePreview dialog ======================================================= }

function GetOpenFileNamePreviewA(lpofn: POPENFILENAMEA): BOOL; stdcall;
  external VFWDLL;
function GetSaveFileNamePreviewA(lpofn: POPENFILENAMEA): BOOL; stdcall;
  external VFWDLL;

function GetOpenFileNamePreviewW(lpofn: POPENFILENAMEW): BOOL; stdcall;
  external VFWDLL;
function GetSaveFileNamePreviewW(lpofn: POPENFILENAMEW): BOOL; stdcall;
  external VFWDLL;

function GetOpenFileNamePreview(lpofn: POPENFILENAMEA): BOOL; stdcall;
  external VFWDLL name 'GetOpenFileNamePreviewA';
function GetSaveFileNamePreview(lpofn: POPENFILENAMEA): BOOL; stdcall;
  external VFWDLL name 'GetSaveFileNamePreviewA';

end.
